Inner Join

Šajā rakstā detalizēti paskatīsimies uz pašu izplatītāko tabulu kombinēšanas veidu – INNER JOIN.

For english speaking only check SQL join types.

Inner Join

Diemžēl man nav īstas skaidrības kā latviski tiek tulkots Inner Join. Līdz ar to esmu spiests visā šai rakstā uz to tā arī atsaukties.

Inner Join tiek lietots, lai atlasītu tos un tikai tos ierakstus no abām tabulām, kur abu tabulu ieraksti atbilst kombinēšanas nosacījumam. Visbiežāk kombinēšanas nosacījums ir tāds, ka pirmās tabulas noteiktas kolonas vērtībām ir jāsakrīt ar otrās tabulas noteiktas kolonas vērtībām. Iedomājamies, ka mums ir tabulas A un B, kā attēlots iepriekšējā rakstā. Tādā gadījumā Inner Join rezultāts grafiski izskatītos šādi:


Inner Join

Sintakse

SELECT <kolonu saraksts>
FROM <kreisās puses tabula>
[INNER] JOIN <labās puses tabula>
ON <kombinēšanas nosacījums>

  • SELECT un FROM klauzas ir aprakstītas iepriekšējā tēmā Vienkāršs SQL Select teikums.
  • Atslēgas vārdu INNER bieži vienkārši atmet un nelieto, bet tas tādā gadījumā vienalga ir INNER join.
  • Pēc atslēgas vārda ON tiek rakstīts kombinēšanas nosacījums. Tas ne vienmēr ir tikai divu kolonu salīdzinājums uz vienādību, bet nosacījumus var kombinēt izmantojot loģiskos operatorus AND, OR, NOT.

Piemēri ir balstīti uz tām pašām tabulām un datiem, kas rakstā par CROSS JOIN.

Piemērs 1. Atlasa personas kodu, vārdu un adreses pilsētu katrai personai.
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
  2  FROM personas
  3  INNER JOIN adreses ON prs_adr_id = adr_id;

PRS_PERSONA PRS_VARDS                                ADR_PILSETA
----------- ---------------------------------------- -------------
23456789012 PĒTERIS                                  TALSI
45678901234 KĀRLIS                                   TALSI
34567890123 ANNA                                     TALSI

INNER join gadījumā ir vienalga, vai papildus nosacījumus raksta kombinēšanas nosacījumā vai WHERE klauzā, protams, atceroties, ka WHERE klauzas nosacījumi tiek nosacīti pielikti klāt ar loģisko AND. Nākamajos 2 piemēros tas ir ilustrēts:

Piemērs 2. Atlasa personas kodu, vārdu un adreses pilsētu katrai personai kombinēšanas nosacījumam pievienojot papildus, ka vārdam jāsākas ar P.
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
  2  FROM personas
  3  INNER JOIN adreses ON prs_adr_id = adr_id
  4    AND prs_vards LIKE 'P%';

PRS_PERSONA PRS_VARDS                                ADR_PILSETA
----------- ---------------------------------------- -------------
23456789012 PĒTERIS                                  TALSI

Piemērs 3. Atlasa personas kodu, vārdu un adreses pilsētu katrai personai šoreiz WHERE klauzā pievienojot papildus nosacījumu, ka vārdam jāsākas ar P. Kā redzams rezultāts ir ekvivalents iepriekšējam Piemēram 2.
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
   2  FROM personas
   3  INNER JOIN adreses ON prs_adr_id = adr_id
   4  WHERE prs_vards LIKE 'P%';
PRS_PERSONA PRS_VARDS                                ADR_PILSETA
 ----------- ---------------------------------------- ----------
 23456789012 PĒTERIS                                  TALSI

Kas notiek, ja kombinēšanas nosacījumā izmanto loģisko OR, var redzēt 4. piemērā. Šeit ir labi redzams, ka patiesībā INNER JOIN ir apakškopa no CROSS JOIN, tas ir, tiek atlasīts arī Dekarta reizinājums visiem tiem Personu ierakstiem, kam vārds sākas ar P.

Piemērs 4. Jābūt ļoti uzmanīgiem kombinēšanas nosacījumā izmantojot loģisko operatoru OR, tas var novest pie interesantām sekām.
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
  2  FROM personas
  3  INNER JOIN adreses
  4  ON prs_adr_id = adr_id OR prs_vards LIKE 'P%';

PRS_PERSONA PRS_VARDS                                ADR_PILSETA
----------- ---------------------------------------- ---------------
23456789012 PĒTERIS                                  RĪGA
23456789012 PĒTERIS                                  TALSI
34567890123 ANNA                                     TALSI
45678901234 KĀRLIS                                   TALSI
23456789012 PĒTERIS                                  VALMIERA

Kas notiek tad, ja kombinēšanas nosacījums vienmēr ir patiess, var redzēt 5. piemērā. Mēs esam atpakaļ pie Dekarta reizinājuma.

Piemērs 5. Ja nosacījums vienmēr ir patiess, tad INNER JOIN degradējās uz CROSS JOIN (Dekarta rezinājumu).
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
  2  FROM personas
  3  INNER JOIN adreses ON 1=1;

PRS_PERSONA PRS_VARDS                                ADR_PILSETA
----------- ---------------------------------------- -------------
12345678910 JĀNIS                                    RĪGA
23456789012 PĒTERIS                                  RĪGA
34567890123 ANNA                                     RĪGA
45678901234 KĀRLIS                                   RĪGA
12345678910 JĀNIS                                    TALSI
23456789012 PĒTERIS                                  TALSI
34567890123 ANNA                                     TALSI
45678901234 KĀRLIS                                   TALSI
12345678910 JĀNIS                                    VALMIERA
23456789012 PĒTERIS                                  VALMIERA
34567890123 ANNA                                     VALMIERA
45678901234 KĀRLIS                                   VALMIERA

12 rows selected.

6. piemērā ir parādīts, ka kombinēšanas nosacījumam ne vienmēr ir jābūt vienādībai. Šajā gadījumā tiek atlasītas personas, kuru adrešu identfikatori nesakrīt ar adreses identifikatoru adreses tabulā. Ir vērts pievērst arī uzmanību tam, ka tā persona, kam lauks prs_adr_id ir NULL netiek atlasīta, jo jebkāda salīdzināšana ar NULL vienmēr dod rezultātu Aplams.

Piemērs 6. Nosacījums var arī nebūt vienādība. Atlasam tos ierakstus no personām, kam adreses identifikators nesakrīt ar identifikatoru adreses tabulā.
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
  2  FROM personas
  3  INNER JOIN adreses ON prs_adr_id <> adr_id
  4  /

PRS_PERSONA PRS_VARDS                                ADR_PILSETA
----------- ---------------------------------------- --------------
23456789012 PĒTERIS                                  RĪGA
34567890123 ANNA                                     RĪGA
45678901234 KĀRLIS                                   RĪGA
23456789012 PĒTERIS                                  VALMIERA
34567890123 ANNA                                     VALMIERA
45678901234 KĀRLIS                                   VALMIERA

Inner Join, protams, var lietot kombinējot tabulu pašu ar sevi. Nākošajā piemērā redzams, ka tabula personas tiek kombinēta ar sevi trīs reizes – vienā gadījumā, kā bērns, otrā kā māte, trešajā kā tēvs. Tātad šis piemērs ilustrē SELF JOIN (kombinēšanu pašam ar sevi), kā arī to, ka, protams, vienā SQL teikumā var kombinēt vairākas tabulas.

Piemērs 7. Piemērs kombinēšanai tabulai ar sevi (SELF JOIN) un vairāku tabulu kombinēšanai vienā SQL teikumā.
SQL> SELECT
  2    tevs.prs_vards "Teva Vārds",
  3    mate.prs_vards "Mātes vārds",
  4    berns.prs_vards "Bērna vārds"
  5  FROM personas berns
  6  INNER JOIN personas tevs ON berns.prs_tevs_id = tevs.prs_id
  7  INNER JOIN personas mate ON berns.prs_mate_id = mate.prs_id;

Teva Vārds        Mātes vārds   Bērna vārds
----------------- ------------- -------------
PĒTERIS           ANNA          KĀRLIS

Alternatīvā sintakse

Šim kombinēšanas veidam var arī izmantot alternatīvo sintaksi, kas ir šāda:

SELECT <kolonu saraksts>
FROM <kreisās puses tabula>, <labās puses tabula>
WHERE <kombinēšanas nosacījums>

Šai sintaksē kombinēšanas nosacījumi tiek rakstīti kopā ar pārējiem nosacījumiem. Visus SQL vaicājumus, kur ir Inner Join, var aizstāt ar šo sintaksi un rezultāts būs tieši tāds pats. Ik pa laikam forumos izraisās diskusijas, kura sintakse ir labāka? Skat. piemēru Should one use ANSI join syntax when writing an Oracle application? It kā šai alternatīvajai sintaksei ir lielākas iespējas iegūst Dekarta reizinājumu, ja aizmirsts kombinēšanas nosacījums, taču, rakstot Inner Join, FROM klauzā nav uzreiz redzamas visas izmantotās tabulas. Mans personīgais viedoklis ir tāds, ka šeit nav pilnīgi viennozīmīgas atbildes, pēc principa vienam patīk māte, otram meita, trešajam kleita 🙂 Man personīgi labāk patīk sintakse, kad visas tabulas raksta FROM klauzā ļoti vienkārša iemesla dēļ – pirms vairāk kā 10 gadiem es tā sāku darīt un tikai relatīvi nesen esmu spiests lietot kombinēšanas sintaksi ar atslēgas vārdiem Inner un Outer.

Piemērs 8. Šis ir ekvivalents piemēram 2. Atlasa personas kodu, vārdu un adreses pilsētu katrai personai kombinēšanas nosacījumam pievienojot papildus, ka vārdam jāsākas ar P. Abas tabulas ir minētas FROM klauzā.
SQL> SELECT prs_personas_kods, prs_vards, adr_pilseta
  2  FROM personas, adreses
  3  WHERE prs_adr_id = adr_id
  4    AND prs_vards LIKE 'P%';

PRS_PERSONA PRS_VARDS                                ADR_PILSETA
----------- ---------------------------------------- ------------
23456789012 PĒTERIS                                  TALSI

Piemērs 9. Šis ir ekvivalents piemēram 7.Piemērs kombinēšanai tabulai ar sevi (SELF JOIN) un vairāku tabulu kombinēšanai vienā SQL teikumā. Viss trīs tabulas ir minētas FROM klauzā.
SQL> SELECT
  2    tevs.prs_vards "Teva Vārds",
  3    mate.prs_vards "Mātes vārds",
  4    berns.prs_vards "Bērna vārds"
  5  FROM
  6    personas berns,
  7    personas tevs,
  8    personas mate
  9  WHERE berns.prs_tevs_id = tevs.prs_id
 10    AND berns.prs_mate_id = mate.prs_id;

Teva Vārds        Mātes vārds   Bērna vārds
----------------- ------------- -------------
PĒTERIS           ANNA          KĀRLIS

Kas jāatceras papildus:

  • Datubāzes ir radītas tam, lai tās kombinētu ierakstus. Tieši ierakstu kombinēšana ir viens no ļoti lielajiem ieguvumiem, ko datubāzes mums dod. Veidojot datubāzes struktūru tiek veikta normalizācija, tas ir, darbības, lai pēc iespējas izvairītos no datu dublicēšanas, savukārt datu ieguves laikā, lai atlasītu informāciju cilvēkiem lasāmā formātā, kombinēšana ir neaizstājama. Tā kā Inner Join ir viens no visbiežāk izmantotajiem kombinēšanas veidiem, tad jāatceras, ka kombinēšana ir jāveic datu bāzē, nevis uz klienta, piemēram, vienā ciklā kasot ārā ierakstu pa ierakstam no vienas tabulas un tad iekšējā ciklā braucot cauri saistītās tabulas ierakstiem.
  • Pārējās klauzas (Group By, Having, Order By), kas ir pieminētas rakstā Vienkāršs SQL Select teikums ir spēkā un darbojas arī tabulu kombinēšanas vaicājumiem.

Turpmākā lasāmviela

P.S. Izskatās, ka vairākos rakstos Inner Join tiek saukts par IEKŠĒJO SAVIENOJUMU, piemēram,

Tādējādi, tā kā nekā labāka nav, tad droši vien tā arī var lietot iekšējais savienojums.

3 Responses to Inner Join

  1. TadeUSH saka:

    Paldies tiešām noderēja 🙂

  2. Sasa saka:

    Es vēlētos, lai sākumā būtu dota tabula visa pilnībā un tad uz šīs tabulas izpildīti vaicājumu. Tā varētu izsekot rezultātiem, kas netiek ņemti un kas tiek paņemti un izvadīti.

  3. Gints Plivna saka:

    Diemžēl, domāju, ka tā nav īsti laba ideja, jo šis raksts ir tikai viens no visu savienojumu saimes. Un pirmajā no detalizētajiem aprakstiem – Dekarta reizinājumā es definēju testa datus un tabulas un pēc tam konsekventi tās lietoju visur ar atsauci, ka tos izmantoju. Drukāt tās atkal un atkal būtu lieka telpas šķiešana, bet nekas jau nekavē otrā logā/tabā atvērt piemērus un skatīties uz visiem reizē.

Komentēt