SQL od podstaw · część 11

WHERE i logika warunków

Wybieraj właściwe wiersze, łącz warunki i przewiduj, jak NULL oraz nawiasy zmienią odpowiedź.

Część bazodanowa INF.03

WHERE wybiera wiersze

SELECT odpowiada na pytanie „które kolumny?”, a WHERE — „które wiersze?”. Warunek jest oceniany dla danych źródłowych. Produkt ma znaleźć się w odpowiedzi tylko wtedy, gdy warunek jest prawdziwy.

SELECT id, nazwa, cena
FROM produkty
WHERE cena >= 60 AND cena < 200
ORDER BY id;

Po resecie otrzymasz Klawiaturę za 120 i Mysz za 60. Monitor jest zbyt drogi, Kabel zbyt tani. Zwróć uwagę na granice: 60 jest włączone przez >=, a 200 wyłączone przez <.

OperatorZnaczeniePrzykład
=równośćid = 2
<>różnośćstatus <> 'nowe’
> / >=większe / większe lub równecena >= 100
< / <=mniejsze / mniejsze lub równeilosc <= 3
ANDoba warunkicena > 50 AND cena < 200
ORco najmniej jeden warunekmiasto = 'Gdansk’ OR miasto = 'Torun’
NOTnegacja warunkuNOT (status = 'nowe’)

Używaj przenośnego <>, zamiast zakładać obsługę każdego skrótu ze swojego języka programowania. SQL używa AND i OR; operatory && i || nie są uniwersalnymi zamiennikami. W niektórych dialektach || oznacza konkatenację tekstu.

Nawiasy opisują intencję

SELECT imie, miasto
FROM klienci
WHERE (miasto = 'Gdansk' OR miasto = 'Torun')
  AND id > 1
ORDER BY id;

Wynik: O’Neil i Adam. Warunek „id większe niż 1” dotyczy obu miast. Bez nawiasów AND wiąże silniej niż OR, więc zapis:

WHERE miasto = 'Gdansk' OR miasto = 'Torun' AND id > 1

oznacza Gdansk lub Torun z id większym niż 1. Dopuści też Alę o id 1. Nawiasy nie są ozdobą; mogą zmienić zestaw zwróconych osób.

TRUE, FALSE i UNKNOWN

NULL w porównaniu wprowadza trzeci wynik logiczny: UNKNOWN. WHERE nie wybiera wiersza dla UNKNOWN. Dlatego klient z nieznanym miastem nie spełnia ani miasto = 'Gdansk', ani miasto <> 'Gdansk'.

ABA AND BA OR B
TRUEUNKNOWNUNKNOWNTRUE
FALSEUNKNOWNFALSEUNKNOWN
UNKNOWNUNKNOWNUNKNOWNUNKNOWN

NOT UNKNOWN nadal daje UNKNOWN. Aby uwzględnić Ewę, zapisz brak miasta jawnie:

SELECT imie, miasto FROM klienci
WHERE miasto <> 'Gdansk' OR miasto IS NULL
ORDER BY id;

Wynik: Jan, Ewa i Adam. Nie zastępuj IS NULL porównaniem = NULL.

Wypróbuj zapytanie

SQLite w przeglądarce — ograniczona emulacja składni MySQL / SQL Server. To nie są rzeczywiste serwery. Ścisłe typy, auto-ID i administrację ćwicz w prawdziwym SZBD.

Ładowanie edytora…

Wyrażenia i aliasy w filtrze

SELECT nazwa, cena * 0.9 AS cena_po_rabacie
FROM produkty
WHERE cena * 0.9 < 100
ORDER BY id;

Wynik to Mysz i Kabel. W WHERE powtarzamy wyrażenie. Alias SELECT nie jest ogólnie dostępny w WHERE tego samego poziomu zapytania w omawianym MySQL i SQL Server. W kolejnym etapie można przenieść obliczenie do podzapytania. Nie myl tej reguły z ORDER BY, gdzie alias zwykle jest dostępny.

Nie zakładaj, że AND zawsze działa jak „krótkie spięcie” w języku programowania i ochroni błędne obliczenie po prawej stronie. Optymalizator może zmienić sposób wykonania. Do bezpiecznego dzielenia przez potencjalne zero używaj konstrukcji właściwej dla danego silnika, np. NULLIF, którą poznasz w funkcjach skalarnych.

To samo pytanie w różnych bazach

Podstawowe porównania oraz AND, OR i NOT mają wspólną postać w MySQL/MariaDB, SQL Server, Oracle 19c i Access/ACE:

SELECT id, nazwa, cena
FROM produkty
WHERE cena >= 60 AND cena < 200
ORDER BY id;

Porównywanie tekstu zależy jednak od kolacji: wielkość liter i akcenty mogą być rozróżniane inaczej. MySQL dopuszcza niektóre automatyczne konwersje, których nie warto używać jako wzorca. Zamiast id = '2' pisz id = 2, zgodnie z typem. SQLite w edytorze nie odtwarza wszystkich konwersji ani kolacji serwerów.

Ćwiczenia

  1. Znajdź produkty droższe niż 100.
  2. Wybierz klientów z Gdanska albo z nieznanym miastem, ale tylko o id większym niż 1.
  3. Znajdź zamówienia inne niż nowe. Co zmieni się, jeśli status będzie NULL?
Rozwiązania
SELECT nazwa FROM produkty WHERE cena > 100 ORDER BY id;
SELECT imie FROM klienci
WHERE (miasto = 'Gdansk' OR miasto IS NULL) AND id > 1
ORDER BY id;
SELECT id FROM zamowienia WHERE status <> 'nowe' ORDER BY id;

1. Klawiatura i Monitor. 2. O’Neil i Ewa. 3. Zamówienia 1 i 3. Gdyby status dopuszczał NULL, taki wiersz nie przeszedłby filtra <> 'nowe’. W danych startowych status jest NOT NULL.

Źródła: operatory logiczne MySQL, SQL Server WHERE, NULL i logika Oracle. INF.03.4: warunki w zapytaniach. Dalej: LIKE, IN, BETWEEN i IS NULL.

Przewijanie do góry