ID FirstName LastName
1 John Doe
2 Bugs Bunny
3 John Johnson
Chcę wybrać DISTINCT
wyniki z FirstName
kolumny, ale potrzebuję odpowiedniego ID
i LastName
.
Zestaw wyników musi pokazywać tylko jeden John
, ale z ID
1 i a LastName
Doe.
DISTINCT
nie jest funkcją. Wszystkie odpowiedzi zDISTINCT()
są błędne. Błąd pojawi się, gdy go nie umieściszSELECT
.ALL
odpowiedzi w nawiasach po wyrazie odrębnym są rzeczywiście błędne. Wyróżnienie NIE jest funkcją, więc nie może zaakceptować parametru. Nawiasy następujące po sobie są po prostu ignorowane. Chyba że używasz PostgreSQL, w którym nawiasy utworzą „złożony typ danych”Odpowiedzi:
spróbuj tego zapytania
źródło
5.7.5+
dotyczący zmienionejGROUP BY
obsługiSłowo
DISTINCT
kluczowe tak naprawdę nie działa w oczekiwany sposób. Podczas używaniaSELECT DISTINCT col1, col2, col3
faktycznie wybierasz wszystkie unikalne krotki {col1, col2, col3}.źródło
Aby uniknąć potencjalnie nieoczekiwanych wyników podczas używania
GROUP BY
bez funkcji agregującej, co jest używane w zaakceptowanej odpowiedzi , ponieważ MySQL może dowolnie pobierać DOWOLNĄ wartość w zbiorze danych, który jest pogrupowany, gdy nie używa funkcji agregującej [sic] i ma problemyONLY_FULL_GROUP_BY
. Proszę rozważyć skorzystanie z wykluczenia.Wyłączenie przyłączenia - jednoznaczne podmioty
Zakładając, że imię i nazwisko są jednoznacznie indeksowane (jednoznaczne) , alternatywą
GROUP BY
jest sortowanie za pomocą aLEFT JOIN
do filtrowania zestawu wyników, zwanego inaczej JOIN wykluczenia.Zobacz demonstrację
Porządek rosnący (AZ)
Aby pobrać odrębne imię uporządkowane według nazwiska z AZ
Pytanie
Wynik
Malejąco (ZA)
Aby pobrać odrębne imię uporządkowane według nazwiska z ZA
Pytanie
Wynik
Następnie możesz uporządkować wynikowe dane według potrzeb.
Wyłączenie dołączenia - niejednoznaczne byty
Jeśli kombinacja imienia i nazwiska nie jest unikalna (niejednoznaczna) i masz wiele wierszy o tych samych wartościach, możesz filtrować zestaw wyników, dołączając warunek OR do kryteriów JOIN, aby również filtrować według identyfikatora.
Zobacz demonstrację
dane nazwa_tabeli
Pytanie
Wynik
Zamówione podzapytanie
EDYTOWAĆ
Moja oryginalna odpowiedź przy użyciu uporządkowanego podzapytania została napisana przed MySQL 5.7.5 , co nie ma już zastosowania z powodu zmian w
ONLY_FULL_GROUP_BY
. Zamiast tego skorzystaj z powyższych przykładów dołączania wykluczeń.Należy również zauważyć; gdy
ONLY_FULL_GROUP_BY
jest wyłączony (oryginalne zachowanie przed MySQL 5.7.5) , użycieGROUP BY
funkcji agregującej może dawać nieoczekiwane wyniki, ponieważ MySQL może dowolnie wybierać DOWOLNĄ wartość w zbiorze danych, który jest pogrupowany [sic] .Oznacza to, że można pobrać wartość
ID
lub, która nie jest powiązana z pobranym wierszem.lastname
firstname
OSTRZEŻENIE
Z MySQL
GROUP BY
może nie przynieść oczekiwanych rezultatów, gdy jest używany zORDER BY
Zobacz przykład przypadku testowego
Najlepszą metodą implementacji, aby zapewnić oczekiwane wyniki, jest filtrowanie zakresu zestawu wyników przy użyciu uporządkowanego podzapytania.
dane nazwa_tabeli
Pytanie
Wynik
Porównanie
Aby zademonstrować nieoczekiwane wyniki podczas używania
GROUP BY
w połączeniu zORDER BY
Pytanie
Wynik
źródło
Ordering is done after grouping.
, więc Nie, nie w tym przypadku użycia, ponadto MariaDB ignoruje ORDER BY w podzapytaniach (zgodnie ze standardem SQL) bez znakuLIMIT
. Chciałbyś użyćWindow Function
Aby uzyskać więcej wyjaśnień, powinieneś zadać pytanie wGROUP BY
można wybrać dowolną wartość w zgrupowanym zestawie danych, chyba że w tych kolumnach zostanie użyta funkcja agregująca w celu wymuszenia określonej wartości. Taklastname
lubid
może pochodzić z dowolnego z uporządkowanych wierszy. Oryginalny przykład podzapytania był domyślnie akceptowalny,MySQL <= 5.7.4
ale technicznie nadal występuje problem. ChociażORDER BY
pomaga zapobiegać losowej selekcji, nadal jest teoretycznie możliwe, ale ze znacznie mniejszym prawdopodobieństwem niż bez korzystania zORDER BY
podzapytania.źródło
HAVING
spowodowało, że moje zapytanie było o 50% wolniejsze.źródło
Co powiesz na
źródło
Nie jestem pewien, czy możesz to zrobić za pomocą MySQL, ale możesz użyć CTE w T-SQL
W przeciwnym razie może być konieczne użycie tabeli tymczasowej.
źródło
Jak zauważył fyrye , zaakceptowana odpowiedź dotyczy starszych wersji MySQL, w których
ONLY_FULL_GROUP_BY
jeszcze nie została wprowadzona. Z MySQL 8.0.17 (użytym w tym przykładzie), chyba że wyłączyszONLY_FULL_GROUP_BY
, pojawi się następujący komunikat o błędzie:Jednym ze sposobów obejścia tego, o którym nie wspomina Fyrye , ale opisano w https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html , jest zastosowanie
ANY_VALUE()
funkcji do kolumn, które są nie wGROUP BY
klauzuli (id
iwlastName
tym przykładzie):Jak napisano w wyżej wymienionych dokumentach,
źródło
ANY_VALUE()
ponieważ moja odpowiedź i komentarze koncentrują się na zapobieganiu dwuznacznym i nieprzewidywalnym zestawom wyników. Ponieważ jak sugeruje nazwa funkcji, może to spowodować pobranie dowolnej wartości z wybranych wierszy. Sugerowałbym użycieMAX
lubMIN
zamiast tego.Pamiętaj o tym, gdy używasz grupy według i porządkuj według tego, że MySQL jest TYLKO bazą danych, która pozwala na używanie kolumn w grupie według i / lub sortowanie według elementów, które nie są częścią instrukcji select.
Na przykład: wybierz kolumnę 1 z grupy tabel według kolumny 2 uporządkuj według kolumny 3
To nie będzie latać w innych bazach danych, takich jak Postgres, Oracle, MSSQL itp. W tych bazach danych musisz wykonać następujące czynności
wybierz kolumnę 1, kolumnę 2, kolumnę 3 z grupy tabel według kolumny 2 uporządkuj według kolumny 3
Tylko niektóre informacje na wypadek, gdybyś kiedykolwiek migrował swój obecny kod do innej bazy danych lub zaczął pracować w innej bazie danych i próbował ponownie użyć kodu.
źródło
Możesz użyć grupy by do wyświetlania różnych wartości, a także odpowiadających im pól.
Teraz masz wyjście takie jak to:
Jeśli chcesz odpowiedzieć jak
następnie użyj tego zapytania,
źródło
Byłby najlepszy zakład IMO
źródło
źródło
DISTINCT()
nie jest funkcją. Również DISTINCT i GROUP BY robią to samo, więc nie ma powodu, aby umieścić je oba.