Это может быть довольно просто, но я не знаю, как это сделать.
У меня есть таблица, в которой могут быть повторяющиеся значения для определенного поля неключевого столбца. Как написать SQL-запрос с помощью Query Builder или Eloquent, который будет извлекать строки с различными значениями для этого столбца?
Обратите внимание, что я беру не только этот столбец, он связан с другими значениями столбца, поэтому distinct()
может не работать. Итак, этот вопрос в основном может заключаться в том, как указать столбец, который я хочу выделить в запросе, который теперь distinct()
не принимает никаких параметров?
where()
он ломается, как я могу это исправить?group by
это не то же самое, чтоdistinct
.group by
изменит поведение агрегатных функций, какcount()
внутри запроса SQL.distinct
не изменит поведение таких функций, поэтому вы получите разные результаты в зависимости от того, какую из них вы используете.В Eloquent вы также можете запросить следующее:
$users = User::select('name')->distinct()->get();
источник
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')
если вы хотите использовать это сchunk
.красноречиво вы можете использовать это
$users = User::select('name')->groupBy('name')->get()->toArray() ;
groupBy фактически выбирает отдельные значения, на самом деле groupBy классифицирует одни и те же значения, чтобы мы могли использовать для них агрегатные функции. но в этом сценарии у нас нет агрегатных функций, мы просто выбираем значение, которое приведет к тому, что результат будет иметь разные значения
источник
in_array()
функции, он никогда не работает. Чтобы исправить это, я попробовал->lists()
(Версия 5.2). Итак,$users = User::select('name')->groupBy('name')->lists('name');
отлично работает для phpin_array()
;Хотя я опоздал с ответом на этот вопрос, лучшим подходом к получению отдельных записей с помощью Eloquent было бы
$user_names = User::distinct()->get(['name']);
источник
get()
методу (и я также тестировал этотfirst()
метод), что эквивалентно использованиюselect()
метода, как показано в нескольких ответах здесь. Хотя почему-тоgroupBy
все равно набирает наибольшее количество баллов. Однако это было бы по-настоящему отличным, если бы я выбирал только этот столбец.$user_names = User::distinct()->count(['name']);
тоже работаетГруппировка по не будет работать, если правила базы данных не позволяют ни одному из выбранных полей находиться за пределами агрегатной функции. Вместо этого используйте коллекции laravel .
$users = DB::table('users') ->select('id','name', 'email') ->get(); foreach($users->unique('name') as $user){ //.... }
Кто-то заметил, что это может не сильно сказаться на производительности для больших коллекций. Я бы порекомендовал добавить ключ в коллекцию. Используемый метод называется keyBy . Это простой метод.
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy('name');
KeyBy также позволяет добавлять функцию обратного вызова для более сложных вещей ...
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy(function($user){ return $user->name . '-' . $user->id; });
Если вам нужно перебирать большие коллекции, добавление ключа решает проблему с производительностью.
источник
Обратите внимание, что
groupBy
использованное выше не будет работать для postgres.Использование
distinct
, вероятно, лучший вариант - например,$users = User::query()->distinct()->get();
Если вы используете,
query
вы можете выбрать все столбцы по запросу.источник
**
Протестировано для Laravel 5.8
**
Поскольку вы хотите получить все столбцы из таблицы, вы можете собрать все данные, а затем отфильтровать их с помощью функции Collections, называемой Unique.
// Get all users with unique name User::all()->unique('name')
или
// Get all & latest users with unique name User::latest()->get()->unique('name')
Для получения дополнительной информации вы можете проверить Документацию коллекции Laravel.
EDIT: у вас могут быть проблемы с производительностью, используя Unique (), вы сначала получите все данные из таблицы User, а затем Laravel отфильтрует их. Этот способ не годится, если у вас много данных о пользователях. Вы можете использовать построитель запросов и вызывать каждое поле, которое хотите использовать, например:
User::select('username','email','name')->distinct('name')->get();
источник
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
извлекает все три кулона для отдельных строк в таблице. Вы можете добавить столько столбцов, сколько захотите.источник
Я обнаружил, что этот метод работает достаточно хорошо (для меня) для создания плоского массива уникальных значений:
$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();
Если вы запустили
->toSql()
этот конструктор запросов, вы увидите, что он генерирует такой запрос:select distinct `name` from `users`
Это
->pluck()
обрабатывается светом \ collection lib (не через sql-запрос).источник
У меня были те же проблемы при попытке заполнить список всех уникальных потоков, которые пользователь имел с другими пользователями. Это помогло мне
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()
источник
$users = Users::all()->unique('name');
источник
Для тех, кто вроде меня совершает ту же ошибку. Вот подробный ответ. Протестировано в Laravel 5.7.
A. Записи в БД
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 ) )
Б. Желаемый сгруппированный результат
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 ) )
Поэтому передавайте только те столбцы
"select()"
, значения которых одинаковы. Например:'type','url'
. Вы можете добавить больше столбцов, если они имеют такое же значение, как'updated_at'
.Если вы пытаетесь пройти
"created_at"
или"id"
в"select()"
, то вы получите записи такой же , как А. Так как они различны для каждой строки в БД.источник
$users = User::all(); foreach($users->unique('column_name') as $user){ code here.. }
источник