Cela peut être assez facile mais je ne sais pas comment le faire.
J'ai une table qui peut avoir des valeurs répétées pour un champ de colonne non clé particulier. Comment écrire une requête SQL à l'aide de Query Builder ou Eloquent qui récupérera des lignes avec des valeurs distinctes pour cette colonne?
Notez que je ne récupère pas uniquement cette colonne, elle est en conjonction avec d'autres valeurs de colonne, donc distinct()
peut ne pas vraiment fonctionner. Donc, cette question peut essentiellement être de savoir comment spécifier la colonne que je veux être distincte dans une requête qui distinct()
n'accepte aucun paramètre?
where()
problème, comment puis-je résoudre ce problème?group by
n'est pas la même chose quedistinct
.group by
changera le comportement des fonctions d'agrégation commecount()
dans la requête SQL.distinct
ne changera pas le comportement de ces fonctions, vous obtiendrez donc des résultats différents selon celle que vous utilisez.Dans Eloquent, vous pouvez également interroger comme ceci:
$users = User::select('name')->distinct()->get();
la source
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')
si vous souhaitez l'utiliser avecchunk
.avec éloquence, vous pouvez utiliser ceci
$users = User::select('name')->groupBy('name')->get()->toArray() ;
groupBy récupère en fait les valeurs distinctes, en fait, groupBy catégorisera les mêmes valeurs, afin que nous puissions utiliser des fonctions d'agrégation sur elles. mais dans ce scénario, nous n'avons pas de fonctions d'agrégation, nous sélectionnons simplement la valeur qui donnera au résultat des valeurs distinctes
la source
in_array()
fonction, cela ne fonctionne jamais. Pour y remédier, j'ai essayé à la->lists()
place (version 5.2). Donc,$users = User::select('name')->groupBy('name')->lists('name');
a bien fonctionné pour phpin_array()
;Bien que je sois en retard pour répondre à cette question, une meilleure approche pour obtenir des enregistrements distincts en utilisant Eloquent serait
$user_names = User::distinct()->get(['name']);
la source
get()
méthode (et j'ai testé aussi à lafirst()
méthode), ce qui équivaut à utiliser laselect()
méthode comme indiqué dans quelques réponses ici. Bien que d'une manière ou d'une autregroupBy
semble toujours marquer le plus haut score. Cependant, ce serait vraiment distinct si c'est la seule colonne que je sélectionne.$user_names = User::distinct()->count(['name']);
fonctionne aussiLe regroupement par ne fonctionnera pas si les règles de la base de données n'autorisent aucun des champs de sélection à être en dehors d'une fonction d'agrégation. Utilisez plutôt les collections laravel .
$users = DB::table('users') ->select('id','name', 'email') ->get(); foreach($users->unique('name') as $user){ //.... }
Quelqu'un a souligné que cela peut ne pas être très performant pour les grandes collections. Je recommanderais d'ajouter une clé à la collection. La méthode à utiliser est appelée keyBy . C'est la méthode simple.
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy('name');
Le keyBy vous permet également d'ajouter une fonction de rappel pour des choses plus complexes ...
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy(function($user){ return $user->name . '-' . $user->id; });
Si vous devez parcourir de grandes collections, l'ajout d'une clé résout le problème de performances.
la source
Notez que
groupBy
tel qu'utilisé ci-dessus ne fonctionnera pas pour les postgres.L'utilisation
distinct
est probablement une meilleure option - par exemple$users = User::query()->distinct()->get();
Si vous utilisez,
query
vous pouvez sélectionner toutes les colonnes comme demandé.la source
**
Testé pour Laravel 5.8
**
Puisque vous voulez obtenir toutes les colonnes de la table, vous pouvez collecter toutes les données, puis les filtrer à l'aide de la fonction Collections appelée Unique
// Get all users with unique name User::all()->unique('name')
ou
// Get all & latest users with unique name User::latest()->get()->unique('name')
Pour plus d'informations, vous pouvez consulter les documentations de la collection Laravel
EDIT: Vous pourriez avoir un problème avec les performances, en utilisant Unique (), vous obtiendrez d'abord toutes les données de la table User, puis Laravel les filtrera. Cette méthode n'est pas bonne si vous avez beaucoup de données d'utilisateurs. Vous pouvez utiliser le générateur de requêtes et appeler chaque champ que vous souhaitez utiliser, par exemple:
User::select('username','email','name')->distinct('name')->get();
la source
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
récupère les trois coulmns pour des lignes distinctes dans le tableau. Vous pouvez ajouter autant de colonnes que vous le souhaitez.la source
J'ai trouvé que cette méthode fonctionnait assez bien (pour moi) pour produire un tableau plat de valeurs uniques:
$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();
Si vous avez exécuté
->toSql()
ce générateur de requêtes, vous verrez qu'il génère une requête comme celle-ci:select distinct `name` from `users`
Le
->pluck()
est géré par illuminate \ collection lib (pas via une requête SQL).la source
J'ai eu les mêmes problèmes en essayant de remplir une liste de tous les threads uniques qu'un utilisateur avait avec d'autres utilisateurs. Cela a fait l'affaire pour moi
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()
la source
$users = Users::all()->unique('name');
la source
Pour ceux qui comme moi font la même erreur. Voici la réponse élaborée Testé dans Laravel 5.7
A. Enregistrements dans DB
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. Résultat groupé souhaité
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 ) )
Alors ne transmettez que les colonnes
"select()"
dont les valeurs sont identiques. Par exemple:'type','url'
. Vous pouvez ajouter d'autres colonnes à condition qu'elles aient la même valeur que'updated_at'
.Si vous essayez de passer
"created_at"
ou"id"
dans"select()"
, alors vous obtiendrez les mêmes que les enregistrements A. Parce qu'ils sont différents pour chaque ligne de DB.la source
$users = User::all(); foreach($users->unique('column_name') as $user){ code here.. }
la source