Esto puede ser bastante fácil, pero no tengo idea de cómo hacerlo.
Tengo una tabla que puede tener valores repetidos para un campo de columna no clave en particular. ¿Cómo escribo una consulta SQL usando Query Builder o Eloquent que obtendrá filas con valores distintos para esa columna?
Tenga en cuenta que no estoy obteniendo solo esa columna, está junto con otros valores de columna, por lo distinct()
que es posible que no funcione. Entonces, esa pregunta básicamente puede ser cómo especificar la columna que quiero que sea distinta en una consulta ahora que distinct()
no acepta parámetros.
where()
se rompe, ¿cómo puedo solucionarlo?group by
no es lo mismo quedistinct
.group by
cambiará el comportamiento de las funciones agregadas comocount()
dentro de la consulta SQL.distinct
no cambiará el comportamiento de dichas funciones, por lo que obtendrá resultados diferentes dependiendo de cuál utilice.En Eloquent también puedes consultar así:
$users = User::select('name')->distinct()->get();
fuente
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 quieres usar esto conchunk
.en elocuente puedes usar esto
$users = User::select('name')->groupBy('name')->get()->toArray() ;
groupBy en realidad está obteniendo los valores distintos, de hecho groupBy categorizará los mismos valores, de modo que podamos usar funciones agregadas en ellos. pero en este escenario no tenemos funciones agregadas, solo estamos seleccionando el valor que hará que el resultado tenga valores distintos
fuente
in_array()
función, nunca funciona. Para solucionarlo, probé en su->lists()
lugar (Versión 5.2). Entonces,$users = User::select('name')->groupBy('name')->lists('name');
funcionó bien para phpin_array()
;Aunque llego tarde para responder a esto, un mejor enfoque para obtener registros distintos usando Eloquent sería
$user_names = User::distinct()->get(['name']);
fuente
get()
método (y también lo he probadofirst()
), lo que equivale a usar elselect()
método como se muestra en algunas respuestas aquí. Aunque de alguna maneragroupBy
todavía parece tener la puntuación más alta. Sin embargo, esto sería realmente distinto si esa es la única columna que estoy seleccionando.$user_names = User::distinct()->count(['name']);
también funcionaLa agrupación por no funcionará si las reglas de la base de datos no permiten que ninguno de los campos seleccionados esté fuera de una función agregada. En su lugar, use las colecciones de laravel .
$users = DB::table('users') ->select('id','name', 'email') ->get(); foreach($users->unique('name') as $user){ //.... }
Alguien señaló que esto puede no ser excelente para el rendimiento de colecciones grandes. Recomendaría agregar una clave a la colección. El método a utilizar se llama keyBy . Este es el método simple.
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy('name');
KeyBy también le permite agregar una función de devolución de llamada para cosas más complejas ...
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy(function($user){ return $user->name . '-' . $user->id; });
Si tiene que iterar sobre colecciones grandes, agregarle una clave resuelve el problema de rendimiento.
fuente
Tenga en cuenta que,
groupBy
como se usó anteriormente, no funcionará para postgres.Usar
distinct
es probablemente una mejor opción, p. Ej.$users = User::query()->distinct()->get();
Si lo usa
query
, puede seleccionar todas las columnas según lo solicitado.fuente
**
Probado para Laravel 5.8
**
Como desea obtener todas las columnas de la tabla, puede recopilar todos los datos y luego filtrarlos usando la función Colecciones llamada Única
// Get all users with unique name User::all()->unique('name')
o
// Get all & latest users with unique name User::latest()->get()->unique('name')
Para obtener más información, puede consultar la documentación de la colección Laravel
EDITAR: Es posible que tenga problemas con el rendimiento, al usar Unique () obtendrá todos los datos primero de la tabla de usuarios, y luego Laravel los filtrará. Esta forma no es buena si tiene muchos datos de usuarios. Puede usar el generador de consultas y llamar a cada campo que desee usar, ejemplo:
User::select('username','email','name')->distinct('name')->get();
fuente
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
recupera los tres coulmns para filas distintas en la tabla. Puede agregar tantas columnas como desee.fuente
Encontré que este método funciona bastante bien (para mí) para producir una matriz plana de valores únicos:
$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();
Si ejecutó
->toSql()
este generador de consultas, verá que genera una consulta como esta:select distinct `name` from `users`
El
->pluck()
es manejado por illuminate \ collection lib (no a través de una consulta sql).fuente
Tuve los mismos problemas al intentar completar una lista de todos los hilos únicos que un usuario tenía con otros usuarios. Esto me sirvió
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()
fuente
$users = Users::all()->unique('name');
fuente
Para aquellos a los que les gusto cometiendo el mismo error. Aquí está la respuesta elaborada Probada en Laravel 5.7
A. Registros en 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. Resultado agrupado deseado
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 ) )
Así que pase solo aquellas columnas
"select()"
cuyos valores sean iguales. Por ejemplo:'type','url'
. Puede agregar más columnas siempre que tengan el mismo valor que'updated_at'
.Si se intenta pasar
"created_at"
o"id"
en"select()"
, por lo que recibirá los registros mismo que A. Debido a que son diferentes para cada fila en la base de datos.fuente
$users = User::all(); foreach($users->unique('column_name') as $user){ code here.. }
fuente