10.4 JOIN un sarežģīti vaicājumi
Stundas uzdevums: Apvienot datus no vairākām tabulām, izmantojot JOIN un agregētas funkcijas.
70 min plāns: Teorija un paraugs (~10 min) · 1. uzdevums (~15 min) - savieno tabulas ar INNER JOIN · 2. uzdevums (~25 min) - salīdzini INNER un LEFT JOIN · 3. uzdevums (~20 min) - izveido TOP sarakstu ar GROUP BY. Papildu uzdevumu sāc tikai tad, ja pārējie trīs ir gatavi.
Pirms sāc: atver savu datubāzi ar tabulām speletaji un speles. Pārliecinies, ka vismaz vienam spēlētājam nav nevienas spēles - to vajadzēs 2. uzdevumā.
Teorija: JOIN un agregēti vaicājumi
JOIN apvieno rindas no divām vai vairākām tabulām, balstoties uz attiecībām (parasti FK ↔ PK).
-- INNER JOIN - tikai tās rindas, kurām ir atbilstība abās tabulās
SELECT s.vards, sp.punkti, sp.spelets
FROM speletaji s
INNER JOIN speles sp ON s.id = sp.speletajs_id
ORDER BY sp.spelets DESC;
-- LEFT JOIN - visi spēlētāji, ieskaitot tos bez spēlēm
SELECT s.vards, COUNT(sp.id) AS speles_skaits
FROM speletaji s
LEFT JOIN speles sp ON s.id = sp.speletajs_id
GROUP BY s.vards;
-- Apvienots: TOP 5 spēlētāju kopējie punkti
SELECT s.vards, SUM(sp.punkti) AS kopa
FROM speletaji s
INNER JOIN speles sp ON s.id = sp.speletajs_id
GROUP BY s.vards
ORDER BY kopa DESC
LIMIT 5;
Praktiskie uzdevumi
1. uzdevums -
Savieno tabulas ar INNER JOIN
Beigās viens vaicājums parādīs datus no abām tabulām.
- Uzraksti
SELECT s.vards, sp.punkti FROM speletaji s. - Pievieno
INNER JOIN speles sp ON s.id = sp.speletajs_id. - Izpildi un pieraksti, cik rindu atgriezās.
- Pievieno
ORDER BY sp.punkti DESC. - Pievieno arī kolonnu
sp.spelets. - Pieraksti, ko nozīmē burti
sunspvaicājumā.
Gatavs, kad: rezultātā katrā rindā ir gan spēlētāja vārds, gan viņa spēles punkti.
2. uzdevums -
Salīdzini INNER un LEFT JOIN
Beigās tu zināsi, kurš JOIN paslēpj datus.
- Pārliecinies, ka vienam spēlētājam nav nevienas spēles.
- Izpildi savu
INNER JOINvaicājumu un meklē šo spēlētāju rezultātā. - Pieraksti, vai viņš tur ir.
- Nomaini
INNER JOINuzLEFT JOINun izpildi vēlreiz. - Pieraksti, kas tagad redzams punktu kolonnā šim spēlētājam.
- Pieraksti, cik rindu atgriež katrs variants.
- Pieraksti vienu secinājumu: kad lietot
LEFT JOIN.
Gatavs, kad: ar INNER JOIN spēlētājs bez spēlēm pazūd, bet ar LEFT JOIN viņš ir redzams ar NULL.
3. uzdevums -
Izveido TOP sarakstu ar GROUP BY
Beigās tev būs īsts rezultātu kopsavilkums.
- Uzraksti vaicājumu ar
COUNT(sp.id) AS speles_skaits. - Pievieno
SUM(sp.punkti) AS kopaunMAX(sp.punkti) AS rekords. - Pievieno
GROUP BY s.vards. - Izpildi un pārbaudi, vai katrs spēlētājs parādās tikai vienu reizi.
- Izņem
GROUP BYrindu un izlasi kļūdu. - Pievieno
ORDER BY kopa DESC LIMIT 5. - Pieraksti vienu secinājumu: kāpēc pie agregātfunkcijām vajag
GROUP BY.
Gatavs, kad: katrs spēlētājs rezultātā parādās vienu reizi ar savu spēļu skaitu, kopsummu un rekordu.
Papildu uzdevums - Filtrē grupas ar HAVING
Ja pamatdarbs ir gatavs, atlasi tikai aktīvos spēlētājus.
- Pievieno vaicājumam
HAVING COUNT(sp.id) >= 2. - Izpildi un pieraksti, cik spēlētāju palika.
- Mēģini to pašu ar
WHEREun izlasi kļūdu. - Pieraksti, ar ko
HAVINGatšķiras noWHERE. - Pievieno arī
AVG(sp.punkti)::INT AS videjie.
Gatavs, kad: rezultātā ir tikai spēlētāji ar vismaz divām spēlēm, un tu vari izskaidrot HAVING.
Biežākās kļūdas
- Aizmirsta GROUP BY: Lietojot agregātu (COUNT, SUM), visi neagregētie lauki jāpievieno GROUP BY.
- Cartesian product: Bez ON nosacījuma JOIN reizina rindu skaitus - vienmēr norādi
ON. - NULL salīdzinājums:
WHERE x = NULLnav pareizi - lietoWHERE x IS NULL.
Koda piemērs
-- TOP 5 spēlētāji ar pilnu statistiku
SELECT
s.vards,
COUNT(sp.id) AS speles_skaits,
SUM(sp.punkti) AS kopa,
AVG(sp.punkti)::INT AS videjie,
MAX(sp.punkti) AS rekords
FROM speletaji s
INNER JOIN speles sp ON s.id = sp.speletajs_id
GROUP BY s.vards
ORDER BY kopa DESC
LIMIT 5;
Anna | 5 | 600 | 120 | 200
Jānis | 3 | 450 | 150 | 200