Isso pode ser muito fácil, mas não tenho ideia de como.
Eu tenho uma tabela que pode ter valores repetidos para um determinado campo de coluna não chave. Como faço para escrever uma consulta SQL usando o Query Builder ou Eloquent que irá buscar linhas com valores distintos para essa coluna?
Observe que não estou buscando apenas essa coluna, ela está em conjunto com outros valores de coluna, portanto, distinct()
pode não funcionar realmente. Então, essa questão basicamente pode ser como especificar a coluna que desejo que seja distinta em uma consulta agora que distinct()
não aceita parâmetros?
where()
ele quebra, como posso consertar isso?group by
não é o mesmo quedistinct
.group by
mudará o comportamento das funções agregadas, comocount()
dentro da consulta SQL.distinct
não mudará o comportamento de tais funções, portanto, você obterá resultados diferentes dependendo de qual usar.No Eloquent, você também pode consultar desta forma:
$users = User::select('name')->distinct()->get();
fonte
Note that I am not fetching that column only, it is in conjunction with other column values
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
->orderBy('name')
se quiser usar isso comchunk
.em eloquente, você pode usar isso
$users = User::select('name')->groupBy('name')->get()->toArray() ;
groupBy está, na verdade, buscando os valores distintos; na verdade, o groupBy categorizará os mesmos valores, para que possamos usar funções de agregação neles. mas neste cenário não temos funções agregadas, estamos apenas selecionando o valor que fará com que o resultado tenha valores distintos
fonte
in_array()
função, ele nunca funciona. Para consertar, tentei->lists()
(versão 5.2). Então,$users = User::select('name')->groupBy('name')->lists('name');
funcionou bem para php'sin_array()
;Embora esteja atrasado para responder, uma abordagem melhor para obter registros distintos usando o Eloquent seria
$user_names = User::distinct()->get(['name']);
fonte
get()
método (e eu testei também para ofirst()
método), o que é equivalente a usar oselect()
método mostrado em algumas respostas aqui. Embora de alguma formagroupBy
ainda pareça ter a pontuação mais alta. No entanto, isso seria verdadeiramente distinto se essa for a única coluna que estou selecionando.$user_names = User::distinct()->count(['name']);
também funcionaO agrupamento por não funcionará se as regras do banco de dados não permitirem que nenhum dos campos selecionados fique fora de uma função de agregação. Em vez disso, use as coleções laravel .
$users = DB::table('users') ->select('id','name', 'email') ->get(); foreach($users->unique('name') as $user){ //.... }
Alguém observou que isso pode não ser ótimo no desempenho de grandes coleções. Eu recomendaria adicionar uma chave à coleção. O método a ser usado é chamado de keyBy . Este é o método simples.
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy('name');
O keyBy também permite adicionar uma função de retorno de chamada para coisas mais complexas ...
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy(function($user){ return $user->name . '-' . $user->id; });
Se você tiver que iterar em grandes coleções, adicionar uma chave para resolver o problema de desempenho.
fonte
**
Testado para Laravel 5.8
**
Como você deseja obter todas as colunas da tabela, pode coletar todos os dados e filtrá-los usando a função de coleções chamada Unique
// Get all users with unique name User::all()->unique('name')
ou
// Get all & latest users with unique name User::latest()->get()->unique('name')
Para mais informações, você pode verificar Documentação da Coleção Laravel
EDITAR: Você pode ter problemas com o desempenho, usando Unique () você obterá todos os dados primeiro da tabela do usuário, e então o Laravel irá filtrá-los. Isso não é bom se você tiver muitos dados de usuários. Você pode usar o construtor de consultas e chamar cada campo que deseja usar, por exemplo:
User::select('username','email','name')->distinct('name')->get();
fonte
Observe que
groupBy
como usado acima, não funcionará para postgres.Usando
distinct
é provavelmente a melhor opção - por exemplo$users = User::query()->distinct()->get();
Se você usar,
query
poderá selecionar todas as colunas conforme solicitado.fonte
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
recupera todos os três canais para linhas distintas na tabela. Você pode adicionar quantas colunas desejar.fonte
Achei esse método funcionando muito bem (para mim) para produzir uma matriz plana de valores únicos:
$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();
Se você executou
->toSql()
neste construtor de consulta, verá que ele gera uma consulta como esta:select distinct `name` from `users`
O
->pluck()
é tratado por illuminate \ collection lib (não via consulta sql).fonte
Tive os mesmos problemas ao tentar preencher uma lista de todos os tópicos exclusivos que um usuário teve com outros usuários. Isso funcionou para mim
Message::where('from_user', $user->id) ->select(['from_user', 'to_user']) ->selectRaw('MAX(created_at) AS last_date') ->groupBy(['from_user', 'to_user']) ->orderBy('last_date', 'DESC') ->get()
fonte
$users = Users::all()->unique('name');
fonte
Pra quem gosta de mim cometendo o mesmo erro. Aqui está a resposta elaborada Testado no Laravel 5.7
A. Registros no banco de dados
Array ( [0] => Array ( [id] => 2073 [type] => 'DL' [url] => 'https://i.picsum.photos/12/884/200/300.jpg' [created_at] => 2020-08-05 17:16:48 [updated_at] => 2020-08-06 18:08:38 ) [1] => Array ( [id] => 2074 [type] => 'PROFILE' [url] => 'https://i.picsum.photos/13/884/200/300.jpg' [created_at] => 2020-08-05 17:20:06 [updated_at] => 2020-08-06 18:08:38 ) [2] => Array ( [id] => 2076 [type] => 'PROFILE' [url] => 'https://i.picsum.photos/13/884/200/300.jpg' [created_at] => 2020-08-05 17:22:01 [updated_at] => 2020-08-06 18:08:38 ) [3] => Array ( [id] => 2086 [type] => 'PROFILE' [url] => 'https://i.picsum.photos/13/884/200/300.jpg' [created_at] => 2020-08-05 19:22:41 [updated_at] => 2020-08-06 18:08:38 ) )
B. Resultado agrupado desejado
Array ( [0] => Array ( [type] => 'DL' [url] => 'https://i.picsum.photos/12/884/200/300.jpg' [updated_at] => 2020-08-06 18:08:38 ) [1] => Array ( [type] => 'PROFILE' [url] => 'https://i.picsum.photos/13/884/200/300.jpg' [updated_at] => 2020-08-06 18:08:38 ) )
Portanto, passe apenas aquelas colunas
"select()"
, cujos valores são iguais. Por exemplo:'type','url'
. Você pode adicionar mais colunas, desde que tenham o mesmo valor'updated_at'
.Se você tentar passar
"created_at"
ou"id"
no"select()"
, então você vai obter os registros mesmo que A. Porque eles são diferentes para cada linha no DB.fonte
// Get unique value for table 'add_new_videos' column name 'project_id' $project_id = DB::table('add_new_videos')->distinct()->get(['project_id']);
fonte
$users = User::all(); foreach($users->unique('column_name') as $user){ code here.. }
fonte