PHPPamokos.lt


5. Ištraukiame reikalingus duomenis - SELECT užklausos

Taigi, dabar žinome apie duomenų bazių lentelių struktūrą ir kaip įterpti/pakeisti duomenis. Priėjome prie svarbiausios ir sudėtingiausios dalies - duomenų ištraukimo su SELECT komanda. Kodėl sudėtingiausia? Nes yra labai daug variantų, kaip galima ištraukti ir atfiltruoti duomenis, apie juos toliau ir kalbėsime.

Kaip jau sakiau, už duomenų ištraukimą atsako komanda SELECT. Ji grąžina iš lentelės tiek eilučių, kiek prašoma užklausoje pagal užklausos sąlygas.

Paprastas pavyzdys:

SELECT title, author FROM books WHERE id = 1;

Išvertus į lietuvių kalbą, ši užklausa skambėtų taip: noriu sužinoti pavadinimą ir autorių knygos, kurios id laukas lygus 1. Beje, ar pamenate WHERE sąlygą iš UPDATE ir DELETE užklausų? Tai būtent taip pat ji veikia ir SELECT sakiniuose - tiesiog nurodote sąlygą, koks laukas turi būti lygus kokiai reikšmei. Tiesa, apie WHERE visokius variantus dar plačiai kalbėsime žemiau.

Bendrai, SELECT užklausa gali būti gana ilga ir susideda iš tokių dalių (kad būtų suprantamiau, kiekvieną dalį atskyriau į atskirą eilutę):

SELECT laukai
FROM lentelės
JOIN kitos_lentelės ON prijungimo_sąlygos
WHERE filtro_sąlygos
GROUP BY grupavimo_taisyklės HAVING filtras_po_grupavimo
ORDER BY rūšiavimo_taisyklės
LIMIT rezultatų_skaičius

Kaip ir minėjau, gali atrodyti sudėtinga, bet išnarpliosime kiekvieną dalį atskirai, ir tada viskas pasidarys aiškiau.

SELECT laukai

Pradėkime nuo pradžių - kokių laukų mums reikia iš lentelės. Tą nurodome iš karto po žodžio SELECT - tai turi būti lentelės laukai, atskirti kableliu. Sakykime, jeigu lentelėje books turime laukus id, title, author, publish_date, price - tai galima ištraukti iš lentelės bet kuriuos iš šių išvardintų laukų, nebūtinai visus:

Jei reikia kelių laukų - juos atskiriame kableliais:

SELECT title, author FROM books WHERE id = 1;

Jei reikia vieno lauko - kablelio nereikia:

SELECT title FROM books WHERE id = 1;

Galime išvardinti ir visus laukus:

SELECT id, title, author, publish_date, price FROM books WHERE id = 1;

Bet jei norime, kad būtų grąžinti visi lentelės laukai - nebūtina jų vardinti, galima tiesiog parašyti toje vietoje žvaigždutę *:

SELECT * FROM books WHERE id = 1;

Tiesa, su žvaigždute būkite gana atidūs. Ji gali atrodyti kaip paprastas būdas - kam vardinti laukus, jei galime tiesiog parašyti žvaigždutę ir visi bus grąžinti, o tada mes jau žiūrime kurių mums reikia. Visa tai yra logiška, bet jeigu lentelėje yra labai daug stulpelių ir daug duomenų, o realiai mums reikia vos keleto stulpelių, tada pati užklausa su žvaigždute gali veikti ilgai ir tokiu būdu duomenų bazės veikimas sulėtės. Tad optimizuojant duomenų bazių greitį, vienas iš pagrindinių patarimų yra SELECT sakiniuose imti tik tuos laukus, kurių iš tikrųjų reikia atvaizdavimui ar tolimesnėms operacijoms.

Kiek žemiau nagrinėsime atvejį, kai SELECT traukia duomenis iš kelių lentelių, tai tokiais atvejais prie lauko galima prirašyti lentelės pavadinimą ir atskirti tai tašku: lentelė.laukas - tai padeda, jeigu skirtingose lentelėse yra laukai su tuo pačiu pavadinimu

SELECT books.title FROM books WHERE id = 1;

FROM lentelė

Kita iš eilės SELECT sakinio dalis atsako į klausimą - iš kokios lentelės norime ištraukti duomenis. Čia, tiesą pasakius, nėra ką labai pasakoti - tiesiog yra nurodomas lentelės pavadinimas po žodžio FROM.

SELECT * FROM books WHERE id = 1;
SELECT * FROM users WHERE name = 'Povilas';

WHERE - įvairios sąlygos filtravimui

Štai ir įdomiausia dalis. Iki šiol matėme tik paprasčiausias WHERE sąlygas - kai kažkoks laukas lygus kažkokiai reikšmei. Bet, kaip ir bet kokioje programavimo kalboje, taip ir SQL struktūroje yra daug daugiau būdų aprašyti sąlygas. Tai, iš esmės, labai panašu į bet kokios programavimo kalbos (PHP, C++, Java ar kt.) IF sąlygų konstravimą ir taip vadinamus "operatorius". Pažiūrėkime į pavyzdžius:

Vėl paprasčiausias pavyzdys - kai laukas lygus kažkokiai konkrečiai reikšmei - jis veikia ir skaičiams, ir teksto eilutėms, tik pastarąsias reikia paimti į apostrofas arba kabutes:

SELECT * FROM books WHERE id = 1;
SELECT * FROM books WHERE title = 'Pirmas';
SELECT * FROM books WHERE title = "Pirmas";

Toliau - aritmetinės operacijos: kai laukas yra didesnis, mažesnis ar nelygus kažkokiai reikšmei

SELECT * FROM books WHERE id != 1;
SELECT * FROM books WHERE id > 1;
SELECT * FROM books WHERE id < 100;
SELECT * FROM books WHERE id >= 100;

Galime įkelti ir kelias sąlygas su žodžiais AND arba OR:

SELECT * FROM books WHERE id = 1 AND title = 'Pirmas';
SELECT * FROM books WHERE id < 100 OR title 'Ne pirmas';

Galime įkelti ir kelias sąlygas su žodžiais AND arba OR:

SELECT * FROM books WHERE id = 1 AND title = 'Pirmas';
SELECT * FROM books WHERE id = 1 OR id = 2;

Jei turite keletą norimų reikšmių - nebūtina rašyti daug OR sąlygų, galima pasinaudoti operatoriumi IN ir jam skliausteliuose paduoti reikšmes per kablelį:

SELECT * FROM books WHERE id IN (1,2,123);

Atvirkščiai, jei turite keletą NEnorimų reikšmių - pridedame žodelį NOT priekyje:

SELECT * FROM books WHERE id NOT IN (1,2,123);

Jei turite reikšmių intervalą NUO-IKI - vėlgi nebūtina rašyti daug OR sąlygų ar netgi IN operatoriaus, yra toks BETWEEN ... AND ... variantas:

SELECT * FROM books WHERE id BETWEEN 5 and 10;

Taip pat galimas ir atvirkštinis variantas - jei norime, kad reikšmė būtų NE iš intervalo NUO-IKI - pridedame žodelį NOT:

SELECT * FROM books WHERE id NOT BETWEEN 5 and 10;

Jeigu laukas gali būti NULL, tai yra tikrinama ne su = NULL operacija, o "žmogiškesniu" užrašymu: IS NULL arba IS NOT NULL:

SELECT * FROM books WHERE author IS NULL;
SELECT * FROM books WHERE price IS NOT NULL;

Atskirai reikia paminėti operatorių LIKE, kuris naudojamas su tekstinėmis eilutėmis. Jis reiškia, kad jūsų duota reikšmė yra dalis lentelės reikšmės, dažniausiai naudojama su % ženklais pradžioje ir pabaigoje:

SELECT * FROM books WHERE author LIKE '%Povilas%';

Šiuo atveju bus grąžintos visos knygos, kurių autorius yra "Povilas" arba "Povilas Autorius" arba "Vytenis Povilas Pavardenis" - žodžiu, kai bet kurioje autoriaus lauko vietoje yra tekstas 'Povilas'.

LIKE būdu galima ieškoti tik tų eilučių, kurios prasideda kažkokia reikšme arba, atvirkščiai, baigiasi kažkokia reikšme - tam nuimame % ženklą, pradžioje arba pabaigoje:

SELECT * FROM books WHERE author LIKE 'Povilas%';
SELECT * FROM books WHERE author LIKE '%Pirmas';

Tiesa, su LIKE duomenų ištraukimu būkite atsargūs: jis veikia sąlyginai lėtai, nes reikia nemažai kompiuterio "pastangų" kad palygintų kiekvieną eilutę ir paieškotų joje tos reikšmės bet kokioje pozicijoje. Tad jei turite lentelę su tūkstančiais įrašų, pagal galimybę stenkitės vengti dažnų LIKE užklausų - o labai dideliems duomenų kiekiams yra atskiri duomenų bazių optimizavimo sprendimai, tokie kaip ElasticSearch ar NoSQL, bet čia jau atskiros temos, kurios nepatenka į šį MySQL kursą.

Taip pat nepamirškite, kad WHERE sąlyga nėra būtina - jei jos nepridėsite, tai bus grąžintos tiesiog visos lentelės eilutės:

SELECT * FROM books;

Štai tiek apie įvairius WHERE variantus.

ORDER BY - rezultatų rūšiavimas

Kai turime rezultatų sąrašą - norimas eilutes - dažnai prireikia jas atitinkamai surūšiuoti: sakykime, pagal abėcėlę, arba nuo didžiausio iki mažiausio skaičiaus. Tam po WHERE sąlygos pridedame ORDER BY sąlygą. Sakykime, paprasčiausias pavyzdys:

SELECT * FROM books where id > 100 ORDER BY id;

Šiuo atveju rezultatai bus surūšiuoti pagal lauko id reikšmę, pradedant nuo mažiausios iki didžiausios.

Jeigu rūšiuojama pagal tekstinį lauką, tai tada bus surūšiuojama pagal abėcėlę:

SELECT * FROM books where id > 100 ORDER BY title;

Jeigu norite rūšiuoti atvirkštine tvarka (nuo didžiausios iki mažiausios reikšmės arba nuo Z iki A), tai po lauko pridedame žodelį DESC (sutrumpinimas nuo "descending"):

SELECT * FROM books where id > 100 ORDER BY title DESC;

Galima rūšiuoti ir pagal kelis laukus iš karto - sakykime, jei vienas laukas turi kelias eilutes su ta pačia reikšme, tai antra rūšiavimo sąlyga gali būti antras laukas:

SELECT * FROM books where id > 100 ORDER BY publish_date DESC, price;

LIMIT - kiek rezultatų grąžinti

SELECT sakinys gali atfiltruoti šimtus ar tūkstančius eilučių - mums to gali būti per daug, juk dažniausiai mums reikia tik pirmųjų dešimties, ar netgi vienos eilutės. Tam skirta sąlyga LIMIT, einanti po ORDER BY sąlygos. Tiesiog rašome LIMIT ir skaičių - kiek eilučių mums reikia grąžinti:

SELECT * FROM books where id > 100 ORDER BY price LIMIT 10;

Taip pat kartais reikia grąžinti X eilučių, bet praleidus pirmąsias Y eilučių - sakykime, reikia atfiltruoti antrą puslapį, jei puslapiuojama po 10 įrašų. Tada po žodžio LIMIT pridedami du skaičiai - pirmasis yra kiek eilučių praleisti, o antrasis po kablelio - kiek eilučių grąžinti. Sakykime, jei norime paimti trečią puslapį, mums reikia praleisti pirmuosius 20 įrašų ir grąžinti sekančius 10:

SELECT * FROM books ORDER BY price LIMIT 20,10;

SUBQUERY ir SUBSELECT - užklausa užklausoje

Sakykime, kad mes darome SELECT * FROM table WHERE id = X, bet to X reikšmės nežinome - jis turi būti rezultatas kitos užklausos. Tarkime, X būtų visų prekių kainų vidurkis. Tai tam galime parašyti vietoje X atskirą SELECT užklausą, kuri grąžins mums reikalingą rezultatą. Pavyzdys:

SELECT * FROM products WHERE price > (SELECT AVG(price) from products);

Taip pat galime naudoti ir IN sąlygą, ir tada SUBSELECT dalyje grąžinti konkretaus lauko reikšmių sąrašą:

SELECT * FROM products WHERE id IN (SELECT product_id FROM orders WHERE price > 100);

O dar galima, kad SUBSELECT dalies rezultatas būtų lentelė, iš kurios po to mes atfiltruojame duomenis pagrindiniame SELECT'e. Tik tokiu atveju šalutiniam rezultatui reikia priskirti pavadinimą su raktažodžiu AS:

SELECT avg(max_price)
FROM
(SELECT customer_id, MAX(price) AS max_price 
 FROM orders 
 GROUP BY customer_id) AS temp_orders;

Apibendrinimas

Štai tiek galima papasakoti apie SELECT užklausą ir jos įvairias sąlygas. Svarbu paminėti, kad šios sąlygos turi būti pateikiamos būtent tokia griežta tvarka - sakykime, jeigu bandysite WHERE įdėti prieš FROM, gausite klaidą. Kituose skyreliuose praplėsime SELECT galimybes su duomenų filtravimu iš kelių lentelių iš karto.



(c) 2015-2018. Visais klausimais kreipkitės povilas@laraveldaily.com