Vezérlőpult
7b. Aggregáció és GROUP BY · Lekérdezések — SELECT

3. blokk · Lekérdezések — SELECT · 7b. témakör

Aggregáció és GROUP BY

Eddig egyes sorokat kérdeztünk le — most összesítünk. Hány termék van? Mennyi az átlagár kategóriánként? Az aggregáló függvények (COUNT, SUM, AVG, MIN, MAX), a GROUP BY csoportosítás és a HAVING csoportszűrés a riportok és statisztikák alapja — végig élőben kipróbálhatóan.

Élő SQL-gyakorló10 kvízkérdés10 feladatWebshop-séma

Tanulási célok

1Mik az aggregáló függvények?

Az aggregáló (összesítő) függvények sok sorból egyetlen értéket számolnak ki. Ahelyett, hogy az egyes termékeket látnánk, a függvény az egész halmazról ad egy összesített számot (darab, összeg, átlag…).

FüggvényMit számolPélda
COUNT()Sorok számaHány termék van?
SUM()Értékek összegeÖsszes készlet darabszáma
AVG()ÁtlagÁtlagos ár
MIN()Legkisebb értékLegolcsóbb termék ára
MAX()Legnagyobb értékLegdrágább termék ára
-- Egyetlen összesített sor a teljes táblából:
SELECT COUNT(*) AS termekek_szama,
       AVG(ar)  AS atlagar,
       MAX(ar)  AS legdragabb
FROM termek;

2COUNT — a leggyakoribb

A COUNT sorokat számol, de fontos a háromféle változata:

FormaMit számol
COUNT(*)Az összes sort (a NULL-okat is).
COUNT(oszlop)Csak azokat a sorokat, ahol az adott oszlop nem NULL.
COUNT(DISTINCT oszlop)Az oszlop különböző (egyedi) értékeinek számát (a NULL-t ez sem számolja).
-- Hány termékhez van egyáltalán megadva kategória? (a NULL-okat kihagyja)
SELECT COUNT(kategoria_id) FROM termek;

-- Hány KÜLÖNBÖZŐ kategóriában van termék?
SELECT COUNT(DISTINCT kategoria_id) FROM termek;
⚠️ COUNT(*) VS COUNT(OSZLOP)

Ha az oszlopban van NULL, a COUNT(oszlop) kevesebbet adhat, mint a COUNT(*)! Ha „hány sor van” a kérdés, használj COUNT(*)-ot.

3SUM, AVG, MIN, MAX

Ezek számértékeken dolgoznak (a MIN/MAX szövegen és dátumon is). A NULL értékeket figyelmen kívül hagyják.

-- A 3-as kategória árstatisztikái:
SELECT SUM(keszlet) AS ossz_keszlet,
       AVG(ar)     AS atlagar,
       MIN(ar)     AS legolcsobb,
       MAX(ar)     AS legdragabb
FROM termek
WHERE kategoria_id = 3;

ROUND — kerekítés

Az AVG gyakran sok tizedesjegyet ad (pl. 73052.5). A ROUND(érték, tizedesjegyek) függvény a kívánt pontosságra kerekít. A második paraméter a megtartandó tizedesjegyek száma — ha elhagyod, egész számra kerekít.

-- Átlagár egész forintra kerekítve:
SELECT ROUND(AVG(ar)) AS atlagar FROM termek;

-- Ugyanaz, két tizedesjegyre kerekítve:
SELECT ROUND(AVG(ar), 2) AS atlagar FROM termek;

-- A ROUND önállóan is működik, nem csak aggregátumon (pl. bruttó ár):
SELECT nev, ROUND(ar * 1.27) AS brutto FROM termek;
✅ ROKON KEREKÍTŐ FÜGGVÉNYEK

Felfelé kerekítés: CEIL() (vagy CEILING()); lefelé: FLOOR(); tizedesjegyek levágása kerekítés nélkül: TRUNCATE(érték, n). Pénznél jellemzően a ROUND(..., 2) a jó választás. (A lenti gyakorlóban a ROUND, CEIL és FLOOR működik; a TRUNCATE MySQL-függvény, ott élesben próbáld ki.)

4GROUP BY — csoportosítás

Eddig a teljes táblát összesítettük egyetlen sorba. A GROUP BY csoportokra bontja a sorokat (pl. kategóriánként), és az aggregáló függvény minden csoportra külön lefut. Így kapunk csoportonkénti darabszámot, átlagot stb.

-- Hány termék van az egyes kategóriákban?
SELECT kategoria_id, COUNT(*) AS db
FROM termek
GROUP BY kategoria_id;

-- Átlag-, min- és maxár kategóriánként:
SELECT kategoria_id,
       COUNT(*)      AS db,
       ROUND(AVG(ar)) AS atlagar,
       MIN(ar)        AS legolcsobb,
       MAX(ar)        AS legdragabb
FROM termek
GROUP BY kategoria_id;
ℹ️ GONDOLKODJ ÍGY

„Csoportonként” → GROUP BY. Ha a kérdésben szerepel az „...onként / ...enként” (kategóriánként, vásárlónként, naponta), szinte biztos, hogy GROUP BY kell hozzá.

5A SELECT-lista aranyszabálya

Ha van GROUP BY, akkor a SELECT-ben szereplő minden oszlop vagy szerepel a GROUP BY-ban, vagy aggregáló függvényben van. Különben a szerver nem tudja, melyik értéket mutassa a csoportból.

-- HIBÁS: a nev nincs sem a GROUP BY-ban, sem aggregálva
SELECT kategoria_id, nev, COUNT(*)
FROM termek
GROUP BY kategoria_id;   -- melyik nevet mutassa a sok termékből??

-- HELYES: csak csoportosító oszlop + aggregátum
SELECT kategoria_id, COUNT(*) AS db
FROM termek
GROUP BY kategoria_id;
⚠️ MYSQL KÜLÖNLEGESSÉG

A MySQL az 5.7-es verzió óta alapból szigorú: az ONLY_FULL_GROUP_BY mód be van kapcsolva, így a fenti hibás lekérdezésre hibaüzenetet kapsz. Régebbi verziókon (vagy kikapcsolt módnál) a szerver csendben egy „véletlenszerű” értéket adott vissza a csoportból — ez csendes hibák forrása volt. A lenti SQLite-gyakorló szintén elnéző: futtasd le, és látni fogod, hogy önkényesen kiválasztott nevet mutat! Éles MySQL-en viszont hibát kapnál — tartsd be a szabályt mindig.

6HAVING — csoportok szűrése

A WHERE az egyes sorokat szűri — de aggregátumra (pl. COUNT(*) > 2) nem hivatkozhatunk benne. Erre való a HAVING: a csoportokat szűri, az aggregálás után.

-- Mely kategóriákban van 1-nél több termék?
SELECT kategoria_id, COUNT(*) AS db
FROM termek
GROUP BY kategoria_id
HAVING COUNT(*) > 1;

-- Mely kategóriák átlagára haladja meg a 20 000 Ft-ot?
SELECT kategoria_id, ROUND(AVG(ar)) AS atlagar
FROM termek
GROUP BY kategoria_id
HAVING AVG(ar) > 20000;

7WHERE vs HAVING

WHEREHAVING
Mit szűrEgyes sorokatCsoportokat
Mikor futAz aggregálás előttAz aggregálás után
Használhat aggregátumot?NemIgen

A kettő együtt is használható: előbb a WHERE kiszűri a nem kívánt sorokat, majd a GROUP BY csoportosít, végül a HAVING szűri a csoportokat.

-- Csak a készleten lévő termékeket nézzük (WHERE), majd a 8000 Ft feletti
-- átlagárú kategóriákat tartjuk meg (HAVING):
SELECT kategoria_id, COUNT(*) AS db, ROUND(AVG(ar)) AS atlagar
FROM termek
WHERE keszlet > 0
GROUP BY kategoria_id
HAVING AVG(ar) > 8000;
ℹ️ A TELJES SORREND

A kulcsszavak kötött sorrendje: SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT. Csoportosított eredményt is rendezhetsz ORDER BY-jal, akár az aggregátum szerint (pl. ORDER BY db DESC).

8Élő SQL-gyakorló

Összesíts a webshopon! A chipek aggregáló és csoportosító mintákat töltenek be — futtasd, majd alakítsd át (pl. más oszlop szerint csoportosíts, vagy módosítsd a HAVING feltételt).

SQL-gyakorló — összesítés és csoportosítás

SQL-motor betöltése…
⚠️ A GYAKORLÓRÓL

A motor SQLite-alapú (a böngészőben fut). Az aggregáló függvények, a GROUP BY és a HAVING gyakorlatilag azonosak a MySQL-lel. (Internetkapcsolat szükséges a motor betöltéséhez.)

9Feladatok

Gyakorló feladatok

⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás — a kódírós feladatokat futtasd is le a fenti élő gyakorlóban!

7b.1⭐

Sorold fel az öt alapvető aggregáló függvényt!

7b.2⭐

Egészítsd ki: a WHERE az ____________ szűri, a HAVING pedig a ____________.

7b.3⭐⭐

Hogyan kapod meg, hány különböző kategóriában van termék? Futtasd is le!

7b.4⭐⭐

Mit ad vissza ez a lekérdezés? Előbb gondold végig, aztán futtasd le!

SELECT kategoria_id, COUNT(*) AS db
FROM termek
GROUP BY kategoria_id;
7b.5⭐⭐

Miért hibás (vagy megbízhatatlan) ez a lekérdezés?

SELECT kategoria_id, nev, COUNT(*)
FROM termek
GROUP BY kategoria_id;
7b.6⭐⭐⭐

Mi a különbség a két lekérdezés eredménye között? (Futtasd le mindkettőt!)

SELECT kategoria_id, COUNT(*) FROM termek GROUP BY kategoria_id HAVING COUNT(*) > 1;
SELECT kategoria_id, COUNT(*) FROM termek WHERE keszlet > 0 GROUP BY kategoria_id;
7b.7⭐

Kódírás: írj lekérdezést, amely megadja a termékek átlagárát és a legdrágább termék árát!

7b.8⭐⭐

Kódírás: add meg kategóriánként a termékek darabszámát és átlagárát, a darabszám szerint csökkenő sorrendben!

7b.9⭐⭐⭐

Kódírás: listázd azokat a kategóriákat, ahol a termékek átlagára meghaladja a 20 000 Ft-ot — csak a készleten lévő termékeket (keszlet > 0) figyelembe véve!

7b.10⭐⭐⭐

Kódírás: a rendeles_tetel táblából add meg rendelésenként a rendelés végösszegét (mennyiség × egységár összege), a legnagyobb összegtől kezdve!

10Önellenőrző kvíz

Ellenőrizd magad!

Minden kérdésnél egy válasz helyes. A végén pontszámot kapsz.

11Fogalomtár

FogalomJelentés
aggregáló függvénysok sorból egy összesített értéket számol
COUNT(*) · COUNT(oszlop) · COUNT(DISTINCT)minden sor · a nem-NULL sorok · az egyedi értékek száma
SUM · AVG · MIN · MAXösszeg · átlag · legkisebb · legnagyobb (NULL-okat kihagyva)
ROUND(x, n)kerekítés n tizedesjegyre (n nélkül egészre)
CEIL · FLOOR · TRUNCATEfelfelé · lefelé kerekítés · tizedesjegyek levágása
GROUP BYcsoportokra bontás — az aggregátum csoportonként számolódik
SELECT-lista szabályaminden oszlop a GROUP BY-ban van vagy aggregálva
ONLY_FULL_GROUP_BYa MySQL szigorú módja (5.7 óta alapértelmezett) — hibát dob a szabály megsértésére
HAVINGa csoportok szűrése az aggregálás után — aggregátumra is
záradéksorrendSELECT → FROM → WHERE → GROUP BY → HAVING → ORDER BY → LIMIT

12Összegzés

  1. Az aggregáló függvények sok sorból egy értéket adnak: COUNT, SUM, AVG, MIN, MAX.
  2. COUNT(*) minden sort, COUNT(oszlop) a nem-NULL sorokat, COUNT(DISTINCT …) az egyedi értékeket számolja.
  3. A GROUP BY csoportokra bontja a sorokat; az aggregátum csoportonként számolódik.
  4. Szabály: a SELECT-listában minden oszlop vagy a GROUP BY-ban van, vagy aggregálva.
  5. A HAVING a csoportokat szűri (aggregátumra is), a WHERE az egyes sorokat (aggregátum nélkül).
  6. Sorrend: WHERE → GROUP BY → HAVING → ORDER BY.