Ściągawka SQL (PostgreSQL)
Instrukcje, których potrzebujesz najczęściej, po jednym przykładzie każda. Przykłady działają na bazie ćwiczeniowej piekarni i używają składni PostgreSQL. Inne bazy różnią się drobnymi szczegółami, które są opisane tam, gdzie mają znaczenie.
Czytaj i filtruj
SELECT wybiera kolumny, FROM wskazuje tabelę, WHERE zachowuje pasujące wiersze, ORDER BY sortuje, LIMIT ogranicza wynik. Tekst wpisuj w pojedynczych apostrofach.
Komentarze są ignorowane: `--` do końca wiersza albo `/* ... */` w wielu wierszach. Używaj ich, żeby wyjaśnić zapytanie, nie zamiast jasnego polecenia.
SELECT name, unit_price FROM products WHERE category = 'pastry' AND unit_price < 3 ORDER BY unit_price DESC LIMIT 5;
Wynik: Ciastka i wypieki poniżej 3.00, od najdroższego.
Wzorce, listy, zakresy i NULL
LIKE dopasowuje wzorce (% to dowolny tekst, _ to jeden znak; ILIKE ignoruje wielkość liter). IN sprawdza listę, BETWEEN sprawdza zakres z obiema granicami, IS NULL znajduje brakujące wartości.
SELECT first_name, loyalty_tier FROM customers WHERE first_name LIKE 'A%' OR loyalty_tier IS NULL ORDER BY first_name;
Wynik: Klienci, których imię zaczyna się na A, albo którzy nie mają poziomu lojalności.
Podsumuj za pomocą GROUP BY
COUNT, SUM, AVG, MIN i MAX zamieniają wiersze w jedną wartość na grupę. WHERE filtruje wiersze przed grupowaniem, HAVING filtruje grupy.
SELECT channel, COUNT(*) AS orders FROM orders GROUP BY channel HAVING COUNT(*) > 5 ORDER BY channel;
Wynik: Tylko kanał online, z 7 zamówieniami.
Łącz tabele
INNER JOIN zachowuje dopasowania, LEFT JOIN zachowuje każdy wiersz lewej tabeli. Nadawaj tabelom krótkie aliasy i zawsze łącz po kluczu.
SELECT p.name, SUM(oi.quantity) AS units FROM products AS p JOIN order_items AS oi ON oi.product_id = p.product_id GROUP BY p.name ORDER BY units DESC, p.name LIMIT 3;
Wynik: Trzy najlepiej sprzedające się produkty.
CASE: if/else w SQL
CASE zwraca wartość pierwszego spełnionego warunku, podobnie jak IFS w Excelu. Bez ELSE zwraca NULL.
SELECT name,
CASE WHEN unit_price < 3 THEN 'budget' WHEN unit_price <= 4 THEN 'standard' ELSE 'premium' END AS band
FROM products
ORDER BY product_id;Wynik: Każdy produkt oznaczony jako budget, standard lub premium.
Podzapytania i WITH
Podzapytanie to zapytanie wewnątrz innego zapytania. WITH nadaje mu nazwę, dzięki czemu główne zapytanie czyta się jak historię.
ANY i ALL porównują wartość z całym podzapytaniem: `> ALL` znaczy większe niż każda wartość, `> ANY` większe niż przynajmniej jedna. `= ANY` to to samo co IN.
WITH spend AS ( SELECT o.customer_id, SUM(oi.quantity * p.unit_price) AS total FROM orders AS o JOIN order_items AS oi ON oi.order_id = o.order_id JOIN products AS p ON p.product_id = oi.product_id GROUP BY o.customer_id ) SELECT customer_id, total FROM spend WHERE total > 30 ORDER BY total DESC;
Wynik: Klient 1 (Lopez) z kwotą 37.10 i klient 3 (Dubois) z kwotą 36.00.
Funkcje okna
OVER dodaje obliczenie w poprzek wierszy bez ich zwijania: rangi, sumy narastające oraz LAG i LEAD dla poprzedniego i następnego wiersza.
SELECT order_id, order_date,
RANK() OVER (ORDER BY order_date) AS day_rank,
LAG(order_date) OVER (ORDER BY order_id) AS prev_date
FROM orders
ORDER BY order_id;Wynik: Każde zamówienie z jego rangą według daty i datą poprzedniego zamówienia.
Zmieniaj dane
INSERT dodaje wiersze, UPDATE je zmienia, DELETE usuwa. Zawsze dodawaj WHERE w UPDATE i DELETE i najpierw uruchom to jako SELECT, żeby zobaczyć, czego dotyczy. Ryzykowne zmiany opakuj w BEGIN i ROLLBACK.
`INSERT INTO t SELECT ...` kopiuje wiersze do tabeli, która już istnieje. `CREATE TABLE t AS SELECT ...` tworzy nową tabelę z zapytania. Klucze całkowite mogą wypełniać się same przez `GENERATED ALWAYS AS IDENTITY` (MySQL: AUTO_INCREMENT; SQL Server: IDENTITY).
UPDATE products SET unit_price = unit_price + 0.10 WHERE category = 'drinks' RETURNING name, unit_price;
Wynik: Dwa napoje z ich nowymi cenami.
Częste pytania
- W jakiej kolejności SQL wykonuje zapytanie?
- Najpierw FROM i JOIN, potem WHERE, GROUP BY, HAVING, SELECT, ORDER BY i na końcu LIMIT. Dlatego WHERE nie może użyć aliasu kolumny z SELECT, ale ORDER BY może.
- Czy SQL rozróżnia wielkość liter?
- Słowa kluczowe oraz nazwy tabel i kolumn nie (PostgreSQL zamienia nazwy bez cudzysłowów na małe litery). Wartości tekstowe już tak: 'Paris' i 'paris' się różnią, chyba że użyjesz ILIKE lub LOWER().
- Czy to działa w MySQL, SQL Server lub SQLite?
- Rdzeń (SELECT, WHERE, GROUP BY, JOIN, CASE) tak. Różnice dotyczą LIMIT (w SQL Server to TOP), łączenia tekstu, funkcji dat i RETURNING. Szczegóły sprawdź w dokumentacji swojej bazy.
- Jak napisać komentarz w SQL?
- Pojedynczy wiersz zaczyna się od -- i trwa do końca tego wiersza. Komentarz blokowy zaczyna się od /* i kończy na */. Baza ignoruje oba. Microsoft Access nie obsługuje komentarzy.
Ćwicz to
- Twoje pierwsze SELECT
- Filtruj wiersze za pomocą WHERE
- Liczenie, sumowanie i grupowanie
- Łączenie tabel za pomocą JOIN
- Warunki w zapytaniu: CASE WHEN
- Ranking i sumy narastające: funkcje okna
- Dodawanie, zmiana i usuwanie wierszy
- Zapytania w zapytaniach: podzapytania, WITH i EXISTS
- Tworzenie tabeli z regułami: CREATE TABLE i transakcje