Może to być dość łatwe, ale nie mam pojęcia, jak to zrobić.
Mam tabelę, która może mieć powtarzające się wartości dla określonego pola kolumny niebędącej kluczem. Jak napisać zapytanie SQL za pomocą narzędzia do tworzenia zapytań lub elokwentu, które pobierze wiersze z różnymi wartościami dla tej kolumny?
Zauważ, że nie pobieram tylko tej kolumny, jest ona połączona z innymi wartościami kolumny, więc distinct()
może nie działać. Więc to pytanie może zasadniczo dotyczyć tego, jak określić kolumnę, która ma być teraz odrębna w zapytaniu, które distinct()
nie akceptuje żadnych parametrów?
where()
że się psuje, jak mogę to naprawić?group by
to nie to samo codistinct
.group by
zmieni zachowanie funkcji agregujących, takich jakcount()
wewnątrz zapytania SQL.distinct
nie zmieni zachowania takich funkcji, więc uzyskasz różne wyniki w zależności od tego, której z nich używasz.W Eloquent możesz również zapytać w ten sposób:
$users = User::select('name')->distinct()->get();
źródło
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')
jeśli chcesz używać tego zchunk
.w wymowny sposób możesz tego użyć
$users = User::select('name')->groupBy('name')->get()->toArray() ;
groupBy w rzeczywistości pobiera różne wartości, w rzeczywistości groupBy kategoryzuje te same wartości, dzięki czemu możemy używać na nich funkcji agregujących. ale w tym scenariuszu nie mamy funkcji agregujących, po prostu wybieramy wartość, która spowoduje, że wynik będzie miał różne wartości
źródło
in_array()
funkcji, nigdy nie działa. Aby to naprawić, spróbowałem->lists()
zamiast tego (wersja 5.2). Więc$users = User::select('name')->groupBy('name')->lists('name');
działało dobrze na phpin_array()
;Chociaż spóźniłem się na odpowiedź, lepszym podejściem do uzyskania odrębnych rekordów za pomocą Eloquent byłoby
$user_names = User::distinct()->get(['name']);
źródło
get()
metody (a testowałem również dofirst()
metody), co jest równoważne użyciuselect()
metody, jak pokazano w kilku odpowiedziach tutaj. Choć jakośgroupBy
nadal wydaje się mieć najwyższy wynik. Jednak byłoby to naprawdę wyraźne, gdyby była to jedyna kolumna, którą wybieram.$user_names = User::distinct()->count(['name']);
działa równieżGrupowanie według nie będzie działać, jeśli reguły bazy danych nie zezwalają na to, aby żadne z wybranych pól znajdowało się poza funkcją agregującą. Zamiast tego użyj kolekcji laravel .
$users = DB::table('users') ->select('id','name', 'email') ->get(); foreach($users->unique('name') as $user){ //.... }
Ktoś zwrócił uwagę, że w przypadku dużych kolekcji może to nie być świetne. Poleciłbym dodanie klucza do kolekcji. Metoda, której należy użyć, nazywa się keyBy . To jest prosta metoda.
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy('name');
KeyBy umożliwia również dodanie funkcji oddzwaniania dla bardziej złożonych rzeczy ...
$users = DB::table('users') ->select('id','name', 'email') ->get() ->keyBy(function($user){ return $user->name . '-' . $user->id; });
Jeśli musisz iterować po dużych kolekcjach, dodanie do nich klucza rozwiązuje problem z wydajnością.
źródło
**
Przetestowano dla Laravel 5.8
**
Ponieważ chcesz pobrać wszystkie kolumny z tabeli, możesz zebrać wszystkie dane, a następnie przefiltrować je za pomocą funkcji Kolekcje o nazwie Unique
// Get all users with unique name User::all()->unique('name')
lub
// Get all & latest users with unique name User::latest()->get()->unique('name')
Więcej informacji można znaleźć w dokumentacji kolekcji Laravel
EDYCJA: Możesz mieć problem z wydajnością, używając Unique () najpierw pobierzesz wszystkie dane z tabeli User, a następnie Laravel je przefiltruje. Ten sposób nie jest dobry, jeśli masz dużo danych użytkowników. Możesz użyć konstruktora zapytań i wywołać każde pole, którego chcesz użyć, na przykład:
User::select('username','email','name')->distinct('name')->get();
źródło
Zwróć na to uwagę
groupBy
jak użyte powyżej nie będzie działać dla postgres.Korzystanie
distinct
jest prawdopodobnie lepszą opcją - np$users = User::query()->distinct()->get();
Jeśli używasz
query
, możesz wybrać wszystkie kolumny zgodnie z żądaniem.źródło
$users = User::select('column1', 'column2', 'column3')->distinct()->get();
pobiera wszystkie trzy coulmns dla różnych wierszy w tabeli. Możesz dodać dowolną liczbę kolumn.źródło
Zauważyłem, że ta metoda działa całkiem dobrze (dla mnie), tworząc płaską tablicę unikalnych wartości:
$uniqueNames = User::select('name')->distinct()->pluck('name')->toArray();
Jeśli uruchomiłeś
->toSql()
ten konstruktor zapytań, zobaczysz, że generuje on takie zapytanie:select distinct `name` from `users`
->pluck()
Jest obsługiwane przez oświetlania \ lib zbiorczej (nie poprzez zapytania SQL).źródło
Miałem te same problemy, gdy próbowałem wypełnić listę wszystkich unikalnych wątków, które użytkownik miał z innymi użytkownikami. To załatwiło sprawę dla mnie
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()
źródło
$users = Users::all()->unique('name');
źródło
Dla tych, którzy lubią mnie, robiąc ten sam błąd. Oto szczegółowa odpowiedź Przetestowana w Laravel 5.7
A. Zapisy w 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. Pożądany wynik zgrupowany
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 ) )
Więc przekaż tylko te kolumny
"select()"
, których wartości są takie same. Na przykład:'type','url'
. Możesz dodać więcej kolumn, pod warunkiem że mają taką samą wartość jak'updated_at'
.Jeśli próbujesz przekazać
"created_at"
lub"id"
w"select()"
, wtedy dostaniesz zapisy samo jak A. Ponieważ są one różne dla każdego wiersza w DB.źródło
// Get unique value for table 'add_new_videos' column name 'project_id' $project_id = DB::table('add_new_videos')->distinct()->get(['project_id']);
źródło
$users = User::all(); foreach($users->unique('column_name') as $user){ code here.. }
źródło