3. blokk · Lekérdezések — SELECT · 7a. témakör
A táblák tele vannak adattal — most jön a lényeg: a lekérdezés. A SELECT a
leggyakrabban használt SQL-utasítás. Ebben a részben az alapokat vesszük: oszlopok
kiválasztása, szűrés (WHERE), rendezés
(ORDER BY), darabszám-korlát
(LIMIT) és az ismétlődések kiszűrése
(DISTINCT) — végig élőben kipróbálhatóan.
A SELECT az SQL lekérdező utasítása (DQL – Data
Query Language). Nem módosít adatot, csak kiolvas: megmondjuk, mely oszlopok,
mely táblából, milyen feltétellel és sorrendben érdekelnek minket.
Egy egyszerű lekérdezés alapszerkezete (a kulcsszavak sorrendje kötött):
SELECT oszlopok -- mit kérünk le FROM tábla -- honnan WHERE feltétel -- milyen szűréssel (opcionális) ORDER BY oszlop -- milyen sorrendben (opcionális) LIMIT n; -- hány sort (opcionális)
Bár a SELECT-et írjuk előre, a szerver logikailag előbb a
FROM-ot és a WHERE-t dolgozza fel
(kiválasztja a sorokat), és csak utána a SELECT oszlopait, majd
az ORDER BY-t és a LIMIT-et. Ez
később (pl. aliasoknál) jól jön.
Megadhatjuk a kívánt oszlopokat felsorolva, vagy a *-gal az
összeset kérhetjük:
-- Minden oszlop: SELECT * FROM termek; -- Csak a megadott oszlopok, ebben a sorrendben: SELECT nev, ar FROM termek;
Az alias (AS) egy ideiglenes, olvashatóbb nevet ad
az oszlopnak az eredményben. Számolt értékeknél különösen hasznos:
SELECT nev AS termeknev, ar AS "Ár (Ft)", ar * 1.27 AS brutto_ar FROM termek;
Az AS kulcsszó elhagyható
(SELECT nev termeknev is működik), de kiírva olvashatóbb. Ha az
alias szóközt vagy egyéb különleges karaktert tartalmaz, tedd idézőjelbe:
AS "Ár (Ft)".
A SELECT-listába nemcsak létező oszlopnevek írhatók — bármilyen kifejezés állhat „oszlopként”, és soronként kiértékelődik:
ar * 1.27 (bruttó ár),
ar * keszlet (készletérték) — akár több oszlopot kombinálva.CONCAT() függvénnyel
oszlopok és szövegek fűzhetők egybe.-- Fix érték: a 7-es minden sorban megjelenik az egyedi_kategoria oszlopban: SELECT nev, ar, 7 AS egyedi_kategoria FROM termek; -- Számolt oszlopok — soronként kiértékelve: SELECT nev, ar, ar * 1.27 AS brutto_ar, ar * keszlet AS keszletertek FROM termek; -- Fix szöveg és összefűzés: SELECT nev, 'webshop' AS forras, CONCAT(nev, ' — ', ar, ' Ft') AS cimke FROM termek;
Leggyakrabban az INSERT ... SELECT-tel együtt hasznos
(6. témakör): átmásolt sorokhoz így adhatunk minden sorban azonos értéket — pl.
SELECT nev, ar, 7 FROM termek ... minden másolatot a 7-es
kategóriába sorol be.
Az oszlop-alias csak az eredményt nevezi át — és nem mindenhol hivatkozhatunk rá:
-- ❌ HIBA: a WHERE még nem ismeri a brutto_ar aliast: SELECT nev, ar * 1.27 AS brutto_ar FROM termek WHERE brutto_ar > 10000; Error: Unknown column 'brutto_ar' in 'where clause' -- ✔ A WHERE-ben az eredeti számítás, az ORDER BY-ban már mehet az alias: SELECT nev, ar * 1.27 AS brutto_ar FROM termek WHERE ar * 1.27 > 10000 ORDER BY brutto_ar DESC;
Nemcsak oszlopnak — táblának is adhatunk aliast
(FROM termek AS t; az AS itt is elhagyható). Ilyenkor viszont a
tábla az eredeti nevén már nem érhető el abban a lekérdezésben:
-- ❌ HIBA: az aliasszal a termek név „elveszett”: SELECT termek.nev FROM termek AS t; Error: Unknown column 'termek.nev' in 'field list' -- ✔ Az aliast kell használni: SELECT t.nev, t.ar FROM termek AS t;
A tábla-alias igazán a több táblás lekérdezéseknél (JOIN — 7c. témakör) lesz fontos, ott szinte mindig használjuk majd.
A lenti SQLite-gyakorló a WHERE-be írt oszlop-aliast elfogadja — az éles MySQL viszont hibát ad rá. Mindig a MySQL-helyes formát használd! A tábla-aliasos hibát a gyakorló is ugyanúgy jelzi.
Éles kódban kerüld a SELECT *-ot: csak a tényleg szükséges
oszlopokat kérd le. Így kevesebb adat utazik, és a kód nem törik el, ha a tábla bővül.
Tanuláshoz/böngészéshez viszont teljesen jó.
A WHERE feltétellel csak azokat a sorokat kapjuk vissza, amelyekre
a feltétel igaz:
-- Csak az 5000 Ft-nál drágább termékek: SELECT nev, ar FROM termek WHERE ar > 5000; -- ÉS: mindkét feltételnek teljesülnie kell: SELECT nev, ar, keszlet FROM termek WHERE ar < 10000 AND keszlet > 0; -- VAGY: elég, ha az egyik teljesül: SELECT nev, kategoria_id FROM termek WHERE kategoria_id = 2 OR kategoria_id = 4; -- NOT: tagadás (ugyanaz, mint a kategoria_id <> 3): SELECT nev, kategoria_id FROM termek WHERE NOT kategoria_id = 3;
Ha AND és OR is van egy feltételben,
használj zárójelet az egyértelműségért: WHERE (a OR b) AND c.
Az AND ugyanis erősebben köt, mint az
OR.
Nézd meg, mekkora a különbség! Ugyanazok a feltételek, csak a zárójel hiányzik:
-- Zárójellel: (2-es VAGY 3-as kategória) ÉS 20 000-nél olcsóbb → 4 találat: SELECT nev, ar, kategoria_id FROM termek WHERE (kategoria_id = 2 OR kategoria_id = 3) AND ar < 20000; -- Zárójel nélkül MÁST jelent, mert az AND köt erősebben: -- kategoria_id = 2 OR (kategoria_id = 3 AND ar < 20000) -- → az ÖSSZES 2-es kategóriás termék bekerül, a 200 000 Ft felettiek is → 7 találat: SELECT nev, ar, kategoria_id FROM termek WHERE kategoria_id = 2 OR kategoria_id = 3 AND ar < 20000;
Mindkettőt lefuttathatod a lenti gyakorlóban — a chipek között is megtalálod.
| Operátor | Jelentés | Példa |
|---|---|---|
= <> != < > <= >= | Összehasonlítás. A „nem egyenlő” jele a szabványos <> vagy a MySQL-ben szintén elfogadott != (a kettő azonos). | ar <> 0, ar != 0 |
AND / OR / NOT | Logikai kapcsolatok | ar < 100 OR keszlet = 0 |
BETWEEN ... AND ... | Tartomány (a két határ is beletartozik) | ar BETWEEN 1000 AND 5000 |
IN (...) | A felsorolt értékek valamelyike | kategoria_id IN (2, 3) |
LIKE | Szövegminta (% = bármennyi karakter, _ = egy karakter) | nev LIKE 'A%' |
IS NULL / IS NOT NULL | Üres (hiányzó) érték vizsgálata | szulo_id IS NULL |
Mindegyik kipróbálható a webshopon:
-- BETWEEN: zárt tartomány (a 3000 és a 16000 is beletartozik): SELECT nev, ar FROM termek WHERE ar BETWEEN 3000 AND 16000; -- IN: rövidebb, mint sok OR — ugyanaz, mint kategoria_id = 2 OR kategoria_id = 4: SELECT nev, kategoria_id FROM termek WHERE kategoria_id IN (2, 4); -- IS NULL: a főkategóriák (amelyeknek nincs szülőjük): SELECT nev FROM kategoria WHERE szulo_id IS NULL;
A NULL „hiányzó értéket” jelent. Sosem vizsgáld = NULL-lal
(mindig hamis lesz!) — helyette IS NULL /
IS NOT NULL. A NULL bármilyen összehasonlításban „ismeretlen”
eredményt ad.
A LIKE mintában két joker (helyettesítő) karakter használható:
% = tetszőleges számú karakter (akár nulla is),
_ = pontosan egy karakter. Fontos: a minta mindig
a teljes értékre illeszkedik — ezért kell a %, ha a „tartalmazza” a cél.
| Minta | Illesztés | Jelentése | Példa találat |
|---|---|---|---|
'M%' | elöl | M-mel kezdődik | Monitor 24 coll |
'%zet' | hátul | „zet”-re végződik | Billentyűzet |
'%egér%' | középen | bárhol tartalmazza az „egér”-t | Vezeték nélküli egér |
'W%r' | elöl + hátul | W-vel kezdődik és r-re végződik | Wi-Fi router |
'_onitor%' | egy joker karakter | bármilyen egy karakter + „onitor…” | Monitor 24 coll |
'egér' | nincs joker | pontos egyezés (ugyanaz, mint az =) | csak a pontosan „egér” nevű |
-- Kezdődik (elöl illesztés): SELECT nev FROM termek WHERE nev LIKE 'M%'; -- Végződik (hátul illesztés): SELECT nev FROM termek WHERE nev LIKE '%zet'; -- Tartalmazza (középen illesztés): SELECT nev FROM termek WHERE nev LIKE '%egér%'; -- Pontosan egy tetszőleges karakter (_): SELECT nev FROM termek WHERE nev LIKE '_onitor%'; -- Tagadás — minden, ami NEM tartalmazza a „coll”-t: SELECT nev FROM termek WHERE nev NOT LIKE '%coll%';
A % nulla karakterre is illeszkedik: a
'Monitor%' minta magára a „Monitor” szóra is igaz. A MySQL
alap-LIKE-ja kis/nagybetűre általában nem érzékeny
('m%' a „Monitor”-t is megtalálja). A tagadása a
NOT LIKE.
Az ORDER BY rendezi az eredményt egy vagy több oszlop szerint.
Alapból növekvő sorrendben rendez (ASC),
csökkenőhöz a DESC kulcsszó kell.
-- Ár szerint csökkenő (legdrágább elöl): SELECT nev, ar FROM termek ORDER BY ar DESC;
Mivel a növekvő sorrend az alapértelmezett, az ASC kulcsszót
nyugodtan elhagyhatjuk — az alábbi két lekérdezés teljesen egyenértékű:
SELECT nev, ar FROM termek ORDER BY ar ASC; -- kiírt ASC SELECT nev, ar FROM termek ORDER BY ar; -- ugyanaz, ASC nélkül
Több oszlopot is megadhatunk vesszővel elválasztva. A rendezés az első oszlop
szerint történik; ahol az értékek egyenlők (döntetlen), ott a második oszlop
dönt, és így tovább. Minden oszlophoz külön megadható az
ASC/DESC irány.
-- Előbb kategória szerint növekvő, az azonos kategóriákon belül ár szerint csökkenő: SELECT nev, kategoria_id, ar FROM termek ORDER BY kategoria_id, ar DESC; -- a kategoria_id-nál az ASC elhagyva
Az ORDER BY kategoria_id, ar DESC a
kategóriát növekvőre (alapértelmezett ASC), az árat viszont
csökkenőre rendezi. A DESC csak az előtte álló oszlopra
(ar) vonatkozik, a kategoria_id-ra
nem. Ha mindkettőt csökkenőre akarod, mindkettőhöz külön ki kell írni:
ORDER BY kategoria_id DESC, ar DESC.
A LIMIT megadja, legfeljebb hány sort kapjunk. Gyakran
ORDER BY-jal együtt használjuk „top N" lekérdezésekhez:
-- A 3 legdrágább termék: SELECT nev, ar FROM termek ORDER BY ar DESC LIMIT 3; -- Lapozás: 5 sort, a 10. sortól kezdve (OFFSET): SELECT nev FROM termek LIMIT 5 OFFSET 10;
A LIMIT + OFFSET párost weboldalakon
lapozáshoz használjuk (pl. „termékek 2. oldala”). Lapozásnál mindig adj meg
ORDER BY-t is, különben a sorrend nem garantált!
A DISTINCT az eredményből eltávolítja az ismétlődő sorokat, így
csak az egyedi értékek maradnak:
-- Mely kategóriákban van egyáltalán termék? (mindegyik csak egyszer) SELECT DISTINCT kategoria_id FROM termek;
A DISTINCT a felsorolt oszlopok együttesére
nézi az egyediséget: SELECT DISTINCT varos, iranyitoszam ...
azokat a város–irányítószám párokat adja, amelyek különböznek.
Próbálj ki bármilyen SELECT-et a webshopon! A séma és a bővített
példaadatok be vannak töltve. A chipekre kattintva betöltődik egy-egy minta — futtasd, majd
alakítsd át!
A motor SQLite-alapú (a böngészőben fut), de a SELECT, WHERE, ORDER BY, LIMIT, DISTINCT és a fenti operátorok gyakorlatilag azonosak a MySQL-lel. (Internetkapcsolat szükséges a motor betöltéséhez.)
⭐ alap · ⭐⭐ haladó · ⭐⭐⭐ kihívás — a kódírós feladatokat futtasd is le a fenti élő gyakorlóban!
Milyen kulcsszóval szűrünk sorokat egy SELECT-ben?
Mit jelent a % és a _ a
LIKE mintában?
Hogyan kérnéd le a termékek 2. oldalát, ha oldalanként 5 terméket mutatsz (ár szerint rendezve)? Futtasd is le!
Mit ír ki ez a lekérdezés? Előbb gondold végig, aztán futtasd le a gyakorlóban!
SELECT nev FROM termek WHERE ar > 100000 ORDER BY ar;
Mi a különbség a két lekérdezés eredménye között? (Futtasd le mindkettőt!)
SELECT kategoria_id FROM termek; SELECT DISTINCT kategoria_id FROM termek;
Miért nem ad eredményt ez a lekérdezés, pedig van olyan kategória, amelynek nincs szülője?
SELECT nev FROM kategoria WHERE szulo_id = NULL;
Kódírás: írj lekérdezést, amely kiírja az összes termék nevét és árát, ár szerint csökkenő sorrendben!
Kódírás: listázd azokat a termékeket (név, ár, készlet), amelyek ára 5000 és 20 000 Ft között van, és van belőlük készleten (keszlet > 0)!
Kódírás: add meg azon termékek nevét és árát, amelyek a 2-es vagy 3-as kategóriába tartoznak, és a nevük tartalmazza a „coll” szót — a legdrágábbtól a legolcsóbbig!
Minden kérdésnél egy válasz helyes. A végén pontszámot kapsz.
| Fogalom | Jelentés |
|---|---|
| SELECT (DQL) | lekérdező utasítás — kiolvas, nem módosít |
| * | az összes oszlop — éles kódban kerülendő |
| alias (AS) | ideiglenes, olvashatóbb név — a WHERE-ben még nem, az ORDER BY-ban már használható; tábla-alias után az eredeti táblanév nem érhető el |
| számolt oszlop · fix érték | a SELECT-listában kifejezés is állhat: ar * keszlet, fix 7 vagy 'szöveg', CONCAT(...) — soronként értékelődik ki |
| WHERE | sorok szűrése feltétellel |
| <> / != | „nem egyenlő” — a kettő MySQL-ben azonos |
| BETWEEN | zárt tartomány: a két határérték is beletartozik |
| IN (...) | a felsorolt értékek valamelyikével egyenlő |
| LIKE · % · _ | szövegminta: % = bármennyi karakter, _ = pontosan egy — elöl/hátul/középen illesztés: 'M%', '%zet', '%egér%' |
| IS NULL | a hiányzó érték vizsgálata (= NULL sosem igaz!) |
| ORDER BY · ASC/DESC | rendezés — alapból növekvő; oszloponként külön irány |
| LIMIT · OFFSET | legfeljebb n sor · kihagyott sorok (lapozás) |
| DISTINCT | ismétlődő sorok/értékek kiszűrése |
SELECT a lekérdező utasítás (DQL); nem módosít, csak
kiolvas.* vagy felsorolás; a SELECT-listában kifejezés is
állhat (számítás, fix érték, CONCAT); olvashatóbb nevek
AS aliasszal — a WHERE-ben az alias még nem használható, és
tábla-alias után az eredeti táblanév sem.WHERE + operátorok: =,
<> (vagy !=),
< > <= >=,
AND/OR/NOT, BETWEEN,
IN, LIKE,
IS NULL.IS NULL-lal vizsgáld, sosem
= NULL-lal.ORDER BY (ASC/DESC, több oszlop) és
LIMIT (+OFFSET) a rendezéshez és korlátozáshoz.DISTINCT kiszűri az ismétlődő sorokat / értékpárokat.