Zapytanie SELECT krok po kroku: kolumny, WHERE z operatorami, LIKE, IN, BETWEEN, IS NULL, sortowanie ORDER BY, LIMIT i DISTINCT. Lekcja 8.4 kursu INF.03.
SELECT (WYBIERZ) to polecenie, które wybiera dane z tabeli. To najczęstsze polecenie SQL na egzaminie: w części pisemnej pytanie z baz danych zwykle pokazuje zapytanie i pyta, co ono zwróci, a w części praktycznej trzy z czterech kwerend to prawie zawsze SELECT. Ta lekcja uczy czytać i pisać zapytania do jednej tabeli. Łączenie dwóch tabel jest w lekcji o złączeniach.
Baza, na której ćwiczymy
Cały dział SQL używa tej samej małej bazy sklepu. Na początek tabela produkt.
[ TABELA PRODUKT ]
id
nazwa
cena
kategoria
sztuk
1
Klawiatura
120
akcesoria
15
2
Mysz
45
akcesoria
0
3
Monitor 24
650
monitory
4
4
Monitor 27
990
monitory
2
5
Kabel HDMI
25
akcesoria
NULL
NULL w kolumnie sztuk znaczy: wartość nieznana. To nie jest zero i nie jest pusty tekst. Wróci to jeszcze w tej lekcji.
Szkielet zapytania
SELECT nazwa, cena FROM produkt;
Czyta się to od końca: z tabeli produkt (FROM, czyli Z) wybierz kolumny nazwa i cena. Kolejność kolumn w wyniku jest taka jak w zapytaniu, a nie taka jak w tabeli. Gwiazdka zastępuje listę kolumn:
SELECT * FROM produkt;
To zwraca wszystkie kolumny i wszystkie wiersze. Na egzaminie praktycznym pierwsze dwie kwerendy to zwykle SELECT * z warunkiem, bo sprawdzają, czy umiesz zawęzić wynik.
AS (JAKO) nadaje kolumnie w wyniku inną nazwę:
SELECT nazwa, cena * 1.23 AS cena_brutto FROM produkt;
Kolumna cena_brutto nie istnieje w tabeli. Powstaje tylko w wyniku i znika po zapytaniu. Tak samo można nazwać kolumnę wyliczoną z dwóch innych albo skrócić długą nazwę.
WHERE: warunek na wiersze
WHERE (GDZIE) zostawia tylko te wiersze, dla których warunek jest prawdziwy.
SELECT nazwa FROM produkt WHERE cena > 100;
Wynik: Klawiatura, Monitor 24, Monitor 27. Mysz i kabel odpadają, bo ich cena nie jest większa niż 100.
Operatory porównania: =, <> (różne; MySQL rozumie też !=), <, >, <=, >=. Warunki łączy się słowami AND (I), OR (LUB) i NOT (NIE).
SELECT nazwa FROM produkt WHERE kategoria = 'akcesoria' AND cena < 100;
Wynik: Mysz, Kabel HDMI. Tekst zawsze stoi w apostrofach, liczba bez. MySQL wybaczy '120' zamiast 120, ale w pytaniach o typy danych ta różnica ma znaczenie.
Pułapka:AND wiąże mocniej niż OR. Warunek a OR b AND c znaczy a OR (b AND c). Kiedy mieszasz oba, stawiaj nawiasy, tak jak w matematyce.
LIKE, IN, BETWEEN: krótsze warunki
LIKE (PODOBNY DO) porównuje tekst ze wzorcem. Znak % zastępuje dowolny ciąg znaków, także pusty. Znak _ zastępuje dokładnie jeden znak.
Wzorzec
Pasuje
Nie pasuje
'Mon%'
Monitor 24, Monitor 27
Mysz
'%HDMI'
Kabel HDMI
Klawiatura
'M___'
Mysz
Monitor 24
'%o%'
Monitor 24, Monitor 27
Mysz
Pytanie z informatora CKE: WHERE imie LIKE '_a%' wybiera imiona, w których a jest DRUGĄ literą: jeden dowolny znak, potem a, potem cokolwiek. Kasia i Marek pasują, Anna nie.
IN (W) sprawdza, czy wartość jest na liście:
SELECT nazwa FROM produkt WHERE kategoria IN ('monitory', 'drukarki');
To samo, co kategoria = 'monitory' OR kategoria = 'drukarki', tylko krócej. Lista może mieć jedną wartość albo dwadzieścia.
BETWEEN (POMIĘDZY) sprawdza przedział, oba końce włącznie:
SELECT nazwa FROM produkt WHERE cena BETWEEN 45 AND 650;
Wynik: Klawiatura, Mysz, Monitor 24. Mysz za 45 wchodzi, bo 45 jest końcem przedziału.
Pułapka:BETWEEN 45 AND 650 to cena >= 45 AND cena <= 650. Odpowiedź z samymi > i <, bez równości, jest w pytaniach najczęstszym błędnym wariantem.
NULL: wartość, której nie ma
NULL nie równa się niczemu, nawet drugiemu NULL. Warunek sztuk = NULL nigdy nie jest prawdziwy, więc takie zapytanie zwraca pusty wynik. Do sprawdzania braku wartości służy osobny operator:
SELECT nazwa FROM produkt WHERE sztuk IS NULL;
SELECT nazwa FROM produkt WHERE sztuk IS NOT NULL;
Pierwsze zapytanie zwraca Kabel HDMI. Drugie zwraca cztery pozostałe produkty. Zwróć uwagę na Mysz: ma sztuk = 0, czyli wartość ZNANĄ (zero sztuk), więc nie jest NULL i przechodzi przez IS NOT NULL.
ORDER BY: kolejność wyniku
Bez ORDER BY (UPORZĄDKUJ WEDŁUG) baza zwraca wiersze w kolejności, jaka jest jej wygodna, zwykle według klucza głównego, ale nikt tego nie obiecuje.
SELECT nazwa, cena FROM produkt ORDER BY cena DESC;
DESC (od descending, MALEJĄCO) daje od najdroższego. ASC (od ascending, ROSNĄCO) jest domyślne, więc ORDER BY cena i ORDER BY cena ASC znaczą to samo. Można sortować po kilku kolumnach: ORDER BY kategoria, cena DESC najpierw ustawia kategorie alfabetycznie, a w obrębie każdej kategorii produkty od najdroższego.
LIMIT i DISTINCT
LIMIT (OGRANICZ) ucina wynik do podanej liczby wierszy. Razem z ORDER BY daje „dwa najtańsze" albo „trzy najnowsze":
SELECT nazwa, cena FROM produkt ORDER BY cena LIMIT 2;
Wynik: Kabel HDMI, Mysz. Bez ORDER BY polecenie LIMIT 2 zwróci dowolne dwa wiersze, więc na egzaminie te dwa słowa idą zawsze razem.
DISTINCT (RÓŻNE) usuwa powtórzenia z wyniku:
SELECT DISTINCT kategoria FROM produkt;
Wynik: akcesoria, monitory. Bez DISTINCT dostaniesz pięć wierszy, bo tyle jest produktów, i trzy z nich będą brzmiały „akcesoria".
W przeglądarce zmień warunek albo kolumnę sortowania i wykonaj zapytanie ponownie:
Części zapytania mają stałą kolejność. MySQL nie przyjmie WHERE napisanego po ORDER BY.
SELECT kolumny
FROM tabela
WHERE warunek
ORDER BY kolumna
LIMIT liczba;
Między WHERE a ORDER BY wchodzą jeszcze GROUP BY i HAVING, opisane w lekcji o funkcjach i grupowaniu.
Na egzaminie
W części pisemnej pytanie pokazuje tabelę z kilkoma wierszami i zapytanie, a odpowiedzi to cztery możliwe wyniki. Metoda: przejdź przez wiersze po kolei i dla każdego sprawdź warunek dokładnie tak, jak zrobiłaby to baza. Zapisz sobie, które wiersze zostają, i dopiero potem patrz na odpowiedzi. Cztery rzeczy, na których pytania łapią najczęściej:
1.
BETWEEN obejmuje oba końce przedziału.
2.
NULL nie przechodzi przez =, tylko przez IS NULL.
3.
% we wzorcu LIKE może zastępować także pusty ciąg, więc 'Mon%' pasuje też do samego słowa Mon.
4.
LIMIT bez ORDER BY nie daje „najmniejszych" ani „największych", tylko pierwsze z brzegu.
W części praktycznej kwerendy zapisuje się w pliku kwerendy.txt i do każdej robi zrzut ekranu wyniku z phpMyAdmin. Zapytanie musi zwracać dokładnie te kolumny, o które prosi arkusz, w tej kolejności. SELECT * tam, gdzie arkusz każe wypisać dwie kolumny, kosztuje punkt.