Apakšvaicājumi – ievads

Apakšvaicājumi ir viena no SQL pamatlietām, ar kuru nākas sastapties jebkuram, kas pēc analoģijas ar gramatiku vēlas izteikties mazliet sarežģītāk nekā vienkāršos nepaplašinātos teikumos. Apakšvaicājumi ir dažādu veidu un katrā DBVS tos mēģina klasificēt un nosaukt diezgan atšķirīgi. Papildus tam gluži tāpat kā tabulu savienojumiem klasificēšanas kritēriji ir dažādi, tāpēc daži veidi var daļēji pārklāties. Attiecīgi šoreiz es necentīšos to visu pārskaitīt un klasificēt, bet parādīšu piemēru, kas to vien dara kā atlasa kaut ko no dual tabulas (speciāla Oracle tabula ar vienu kolonu dummy un vienu rindu, kas satur ‘X’). Daži termini varētu būt specifiski Oracle izpratnei par šo jomu, bet jēga jau nosaukuma dēļ nemainās; ja jūs zināt ko šis veids dara, tad arī citās DBVS, tas darīs to pašu, tikai varbūt tiks saukts citādi. 

Jau iepriekš brīdinu – nemeklējiet šajā piemērā nekādu semantisku jēgu, izņemot tikai to, ka tas ir lietots kā piemērs tam, kur tik vien apakšvaicājumus nevar iebāzt.

WITH a AS (SELECT * FROM dual)
SELECT (SELECT 1 FROM dual) col1, 3 col2
FROM (SELECT * FROM a) outer1,
  (SELECT * FROM a)
INNER JOIN (SELECT * FROM a)
  ON (1=(SELECT 1 FROM dual))
WHERE 1 >= ANY (
  SELECT 1 FROM dual
  UNION ALL
  SELECT 2 FROM dual
)
  AND EXISTS (SELECT 1 FROM dual)
  AND 1 IN (SELECT 1 FROM dual)
  AND EXISTS (
    SELECT 1 FROM dual inner
    WHERE outer1.dummy = inner.dummy
  )
GROUP BY 1
HAVING count(*) >= (SELECT 1 FROM dual)
ORDER BY (SELECT 1 FROM dual);

Tālāk šis pats SQL vaicājums ir krietni krāsainākā variantā:

Apakšvaicājumu piemērs

Apakšvaicājumu piemērs

Kas šeit ir kas?

  • Sarkanā krāsā ir iezīmētas vienkārša SQL Select teikuma sastāvdaļas.
  • 1 – SQL with klauza. Oracle to sauc par subquery factoring klauzu, savukārt SQL server par common table expression. Arī ar to var sākties Select teikums un tā galvenā ideja ir iznest ārā kopīgas SQL teikuma sastāvdaļas.
  • 2 – with klauzas vaicājums. Tālāk Select vaicājumā var lietot definēto apakšvaicājumu a (iezīmētu melnā krāsā) un “atlasīt” datus no tā.
  • 3 – apakšvaicājums kolonas vietā, saukts arī par skalāro apakšvaicājumu (scalar subquery). Kā jau pats nosaukums norāda, šim apakšvaicājuma veidam ir jāatgriež tieši viena vērtība, t.i. jāatlasa viena ieraksta viena kolona, kas protams var būt arī izteiksme. Visi zīmējumā iekrāsotie apakšvaicājumi dzeltenā krāsā ir skalārie apakšvaicājumi.
  • 4 – piemērs tam, ka savienojumus jeb tabulu kombinēšanas nebūt nav jāveido tikai no tabulām, bet tie var būt apakšvaicājumi. Kā redzam piemērā ir miksēta tabulu kombinēšana izmantojot sintaksi, kad kombinējamās ierakstu kopas vienkārši raksta FROM klauzā atdalot ar komatu (pirmā un otrā, faktiski tur ir Dekarta reizinājums, jo WHERE klauzā nav nekāda kombinēšanas nosacījuma), kā arī raksta tiešu ANSI savienojumu sintaksi izmantojot INNER JOIN atslēgas vārdu. Apakšvaicājumus FROM klauzā sauc arī par iekļautajiem skatījumiem (inline view). Tas ir mans brīvs tulkojums, jo izskatās, ka pat Google latviešu lapās šādu terminu praktiski atrast nespēj.
  • 5 – piemērs jau augstāk minētajam skalārajam apakšvaicājumam, šoreiz tas lietots kombinēšanas nosacījumā.
  • 6 – apakšvaicājums WHERE klauzā, tādus sauc arī par nested subquery (šķiet latviski būtu ligzdvaicājums, izbēgot no “apakš“. Par “ligzd” skat. pamatojumu šeit un iebildes šeit). Šajā gadījumā tiek izmantots modificēts (ar atslēgas vārdu ANY) lielāks vienāds operators. Tā kā šis operators ir modificēts, tad var apakšvaicājumā atlasīt arī vairākus ierakstus.
  • 7 – apakšvaicājums WHERE klauzā izmantojot EXISTS operatoru.
  • 8 – apakšvaicājums WHERE klauzā izmantojot IN operatoru.
  • 9 – it kā tas pats EXISTS operators, kas punkta 7. Bet ir viena atsķirība – šo apakšvaicājumu ir jāizpilda katrai virsvaicājumā atlasītajai rindiņai, jo tas ir atkarīgs no virsvaicājuma atlasītā ieraksta. Šādus apakšvaicājumus, kur rezultāts ir atkarīgs no virsvaicājuma atlasītā ieraksta, sauc par korelētajiem apakšvaicājumiem (correlated subquery). Protams, ka korelētais apakšvaicājums var būt arī citiem operatoriem, ne tikai EXISTS.
  • 10 – skalārais apakšvaicājums HAVING klauzā.
  • 11 – skalārais apakšvaicājums ORDER BY klauzā.

Dažas papildus piezīmes

  • Apakšvaicājuma galvenā jēga ir uzzināt kaut ko tādu, ko vienā vaicājumā vien sakombinēt nav iespējams, vai arī tas ir pārāk sarežģīti.
  • Kā redzams apakšvaicājumi var ielīst daudz un dažādās vietās. Protams, dažkārt tiem var būt šādi tādi ierobežojumi, bet tas ir jāskatās katrā gadījumā atsevišķi.
  • Apakšvaicājumi, protams, ir pielietojami arī Insert, Update, Delete un Merge teikumos, ne tikai Select.
  • Ir vērts atcerēties, ka katrs apakšvaicājums var savukārt būt pietiekami sarežģīts, atlasīt datus no vairākām tabulām, kā arī nekas mūs nekavē veidot iekļautus apakšvaicājumus vairākos līmeņos. Tehniski parasti tam ir kādas robežas, bet tās ir daudz tālāk nekā jebkurš saprātīgs un lasāms SQL teikums pieļautu.
  • Apakšvaicājumi un tabulu savienojumi (join) var tikt lietoti, lai funkcionāli sasniegtu vienu un to pašu rezultātu. Ne visu ko var sasniegt ar apakšvaicājumiem, var sasniegt ar savienojumiem, tāpat ne visu ko var sasniegt ar savienojumiem, var sasniegt ar apakšvaicājumiem. Tās ir divas dažādas lietas, ko SQL piedāvā un abas var tikt lietotas, lai panāktu vēlamo rezultātu. Nav iespējams pateikt, ka vienmēr labāki ir savienojumi, tāpat kā nav iespējams pateikt, ka vienmēr labāki ir apakšvaicājumi.
  • Dažas datu bāzu vadības sistēmas apakšvaicājumus uztver mierīgāk, dažas ne tik mierīgi 🙂 Piemēram MySQL, šķiet nav diez ko draudzīgs apakšvaicājumiem, jo vismaz FROM klauzas apakšvaicājumus katru izrēķina atsevišķi. Tas tikai vēl vairāk pastiprina izteikumu – it depends, nirvānu (vēlamo rezultātu) var sasniegt pa daudziem un dažādiem ceļiem un nebūt nav tikai viens vienīgais pareizais.
  • Oracle (un iespējams arī citās DBVS) izpildes plāna veidošanas laikā Optimizators vispār var transformēt savienojumu par apakšvaicājumu un otrādi, ja to uzskata par vajadzīgu un tas konkrētā gadījumā ir iespējams. Tāpēc šī robeža ir vēl jo vairāk izplūdusi.

Tālākā lasāmviela

Turpinājums sīkāk par katru no veidiem kaut kad sekos 🙂

Atbildēt

Fill in your details below or click an icon to log in:

WordPress.com logotips

You are commenting using your WordPress.com account. Log Out /  Mainīt )

Facebook photo

You are commenting using your Facebook account. Log Out /  Mainīt )

Connecting to %s

%d bloggers like this: