SQL:n joukko-operaattorit: IN, BETWEEN ja UNION
SQL-lauseiden operaattorit mahdollistavat tietojen vertailun, yhdistämisen ja muokkaamisen osana kyselyä. Ne määrittävät, millä ehdoilla ja logiikalla tietoa käsitellään — tämän takia ne ovat olennainen SQL-kielen toimintaa. Operaattorit jaetaan perinteisesti kuuteen pääryhmään: aritmeettiset, vertailu-, merkki-, loogiset, joukko- ja muut operaattorit.
Miten SQL:n joukko-operaattorit auttavat käsittelemään suuria tietomassoja?
SQL:n joukko-operaattorit yhdistävät usean eri SQL-kyselyn tulokset ja kohdentavat kyselyt arvojoukkoon (yksittäisten arvojen asemasta). Niitä kannattaa käyttää selkeyttämään koodia ja optimoimaan suorituskykyä, erityisesti suurissa tuotantotietokannoissa.
Kaikki joukko-operaattorit vaativat, että yhdistettävät kyselyt palauttavat saman määrän sarakkeita ja että tulosjoukkojen sarakkeet ovat samaa tietotyyppiä.
Voit tutustua SQL:n joukko-operaattoreiden käyttöön käytännönläheisten harjoitusten kautta SQL-kursseillamme.
Miksi IN-operaattori voi hidastaa SQL-kyselyä ja milloin käyttää EXISTS-rakennetta?
IN-operaattori vertailee sarakkeen arvoa useaan vaihtoehtoon ilman pitkää OR-ketjua.
Se tekee kyselystä helpommin luettavan ja ylläpidettävän:
SELECT Merkki, Malli, Tuotteet
FROM Tuotteet
WHERE Malli IN ('LADA','SKODA', 'VOLVO' );
Vastaava kysely olisi OR-operaattorin kautta toteutettuna näyttää seuraavalta:
SELECT Merkki, Malli, Tuotteet
FROM Tuotteet
WHERE Malli = 'LADA' OR Malli = 'SKODA' OR Malli = 'VOLVO';
IN-operaattori on useimmissa tietokannoissa hieman tehokkaampi vaihtoehto kuin OR-operaattori. Erityisesti tästä nopeushyödystä pääsee nauttimaan jos arvojoukko on kiinteä lista ja käsiteltävä sarake on indeksoitu. Suuret arvolistat ilman indeksiä voivat puolestaan hidastaa kyselyä merkittävästi.
Erityisen ongelmallisia suorituskyvyn kannalta ovat alikyselyt, jotka käyttävät IN-operaattoria.
Näissä tilanteissa EXISTS-rakenne on usein suorituskykyisempi vaihtoehto suurilla datamäärillä.
Alla olevassa esimerkissä noudamme kaikki tuotteet, joista on tehty vähintään yksi tilaus.
IN-operaattoria käyttävä kysely lukee koko alikyselyn tulosjoukon muistiin ja vertaa sitten pääkyselyn rivejä siihen.
EXISTS-operaattorilla kysely toimii "korrelaationa": tietokanta tarkistaa vain, löytyykö Tilaukset-taulusta yksikin rivi, joka täyttää ehdon.
SELECT Nimi, Hinta
FROM Tuotteet
WHERE ID IN (SELECT TuoteID FROM Tilaukset);
SELECT T.Nimi, T.Hinta
FROM Tuotteet T
WHERE EXISTS (
SELECT 1
FROM Tilaukset O
WHERE O.TuoteID = T.ID
);
Miljoonia rivejä sisältävillä tulosjoukoilla ero näiden kahden kyselyn välillä mitataan jopa tunneissa ja pahimmillaan datan kirjoittamisena levylle - ja järjestelmän sammumisena. Jos raskaiden SQL-kyselyiden optimointi kiinnostaa sinua, järjestämme tilauksesta SQL-kyselyiden tuning ja optimointikoulutuksia.
Miksi SQL:n BETWEEN-operaattori edellyttää huolellisuutta päivämäärien kanssa?
BETWEEN-operaattorilla tarkistetaan sijoittuuko arvo määritellyn välin rajojen sisään.
Se soveltuu erityisesti lukuarvojen tai päivämäärien vertailuun:
SELECT Merkki, Malli, Tuotteet
FROM Tuotteet
WHERE Tuotteet BETWEEN 10000 AND 50000;
Päivämäärien vertailussa on hyvä huomata, että jos kentän tietotyyppi on DATETIME, tulee raja ilmaista tarkasti — tai vaihtoehtoisesti käyttää seuraavan päivän alkua rajana.
Ilman tätä ratkaisua BETWEEN-operaattori voi jättää osan päivän viimeisistä tapahtumista huomioimatta.
SELECT Merkki, Malli, Tuotteet
FROM Tuotteet
WHERE Lisätty BETWEEN '2026-01-01 00:00:00.000' AND '2026-01-02 23:59:59.999';
SELECT Merkki, Malli, Tuotteet
FROM Tuotteet
WHERE Lisätty BETWEEN '2026-01-01' AND '2026-01-03';
Mitä eroa on UNION ja UNION ALL -operaattoreilla on kyselyn suorituskyvyn kannalta
UNION palauttaa kahden kyselyn tulokset ja poistaa kaksoisarvot (eli saman rivin esiintymät).
Seuraava kysely palauttaa kaikki eri automerkit molemmista tauluista:
SELECT Merkki FROM Tuotteet
UNION
SELECT Merkki FROM Menopelit;
UNION-kyselyt voivat kuluttaa paljon muistia, koska tietokanta joutuu vertailemaan jokaista riviä.
Tämä voi johtaa levyvälimuistin käyttöön tuotannossa.
Jos tiedät, ettei duplikaatteja tule (tai niillä ei ole merkitystä), käytä aina UNION ALL-kyselyä.
Se on huomattavasti nopeampi, koska tietokannan ei tarvitse tehdä raskasta lajittelua ja vertailua duplikaattien poistamiseksi.
UNION ALL toimii kuten UNION, mutta säilyttää kaikki rivit, myös kaksoisarvot.
Seuraava kysely voi siis palauttaa saman merkin useita kertoja:
SELECT Merkki FROM Tuotteet
UNION ALL
SELECT Merkki FROM Menopelit;
Miten vertailla kahta tietojoukkoa SQL:n INTERSECT- ja MINUS-operaattoreilla?
INTERSECT eli leikkaus palauttaa vain rivit, jotka esiintyvät molempien kyselyiden tulosjoukoissa:
SELECT Merkki FROM Tuotteet
INTERSECT
SELECT Merkki FROM Menopelit;
MINUS eli erotus palauttaa ensimmäisen kyselyn rivit, jotka eivät ole mukana toisessa kyselyssä.
SELECT Merkki FROM Tuotteet
MINUS
SELECT Merkki FROM Menopelit;