Usuwanie powtarzających się wierszy z wyniku zapytania słowem DISTINCT i pułapka porównywania całych wierszy, a nie pojedynczych kolumn.
Wynik zapytania często zawiera powtórzenia. Pytanie „jakie przedmioty są w tabeli ocen" zadane zwykłym SELECT zwróci nazwę przedmiotu tyle razy, ile jest z niego ocen – a nas interesuje sama lista, bez powtórzeń. Od tego jest słowo kluczowe DISTINCT.
DISTINCT stawia się zaraz po SELECT, przed listą kolumn. Baza wykonuje zapytanie normalnie, a na koniec usuwa z wyniku powtarzające się wiersze, zostawiając po jednym egzemplarzu każdego.
Reguła, którą trzeba zapamiętać: DISTINCT porównuje CAŁY wiersz wyniku, nie pojedynczą kolumnę. Dwa wiersze zostaną uznane za takie same tylko wtedy, gdy zgadzają się we wszystkich wypisanych kolumnach. Wystarczy, że w którejkolwiek różnią się choćby jednym znakiem, a oba zostaną w wyniku.
Stąd bierze się najczęstsze nieporozumienie. Zapytanie o same nazwiska z DISTINCT faktycznie zwróci listę unikalnych nazwisk. Ale gdy dopiszesz do listy kolumn imię, DISTINCT zacznie porównywać pary „imię plus nazwisko" – i dwie różne osoby o tym samym nazwisku obie zostaną w wyniku, bo różnią się imieniem. To poprawne działanie, tylko rzadko to, czego się spodziewano.
Odwrotna pułapka jest groźniejsza: DISTINCT nie odróżnia dwóch różnych osób o identycznych danych. Jeśli w tabeli są dwie różne uczennice nazywające się tak samo, DISTINCT skróci je do jednego wiersza – bo widzi wyłącznie wartości, nie rzeczywistość, którą opisują. Dlatego do liczenia osób służy klucz (id), a nie nazwisko.
Jeśli powtórzeń chcesz nie tyle usunąć, ile policzyć, właściwym narzędziem jest GROUP BY – grupowanie bez funkcji agregującej daje zresztą wynik bardzo podobny do DISTINCT.
-- Bez DISTINCT: przedmiot powtarza się tyle razy, ile jest z niego ocen SELECT przedmiot FROM oceny
| przedmiot |
|---|
| informatyka |
| matematyka |
| informatyka |
| informatyka |
| matematyka |
-- Z DISTINCT: sama lista przedmiotów SELECT DISTINCT przedmiot FROM oceny
| przedmiot |
|---|
| informatyka |
| matematyka |
-- DISTINCT patrzy na cały wiersz - tu na pary przedmiot + ocena SELECT DISTINCT przedmiot, ocena FROM oceny
| przedmiot | ocena |
|---|---|
| informatyka | 5 |
| matematyka | 4 |
| informatyka | 3 |
| informatyka | 6 |
| matematyka | 5 |
Zanim dopiszesz DISTINCT, sprawdź, które kolumny są w SELECT. Dodanie do listy kolumny o unikalnych wartościach – zwłaszcza id – sprawia, że DISTINCT przestaje cokolwiek usuwać, bo każdy wiersz staje się z definicji niepowtarzalny. To najczęstsza przyczyna sytuacji „napisałem DISTINCT, a duplikaty dalej są".
Uważaj też na polecenia typu „ile jest różnych…". Samo DISTINCT niczego nie liczy – zwraca listę. Do policzenia potrzebna jest funkcja agregująca, a jeśli zadanie pyta o liczbę różnych wartości, warto sprawdzić, czy Twoja baza pozwala policzyć unikaty wprost wewnątrz funkcji zliczającej.
Tak, bo baza musi porównać wiersze między sobą, żeby wykryć powtórzenia. Przy tabelach z zadania maturalnego jest to niezauważalne, ale to powód, dla którego DISTINCT nie dopisuje się „na wszelki wypadek".
Nie. Wynik bywa uporządkowany przy okazji porównywania wierszy, ale nie jest to obiecane – jeśli kolejność ma znaczenie, dopisz ORDER BY.
Wszystkie puste wartości w danej kolumnie uznaje za jedną i zostawia z nich jeden wiersz. To wyjątek od ogólnej zasady, że pustych wartości nie da się ze sobą porównać.
Zagadnienia z tego samego obszaru matury – warto je powtórzyć razem: