SQL Müsahibə Suallarına qoşulur

Qeyd nədir və nə üçün tələb olunur?

Verilənlər bazası əsasən bir çox cədvəldən ibarətdir. Bir anda hər hansı bir cədvələ daxil olsaq, verilənlər bazasından həqiqi istifadə etməyəcəyik. Məsələn, bir işçi məlumat bazasını nəzərdən keçirin. İşçi deyəndə Verilənlər bazası, EMPLOYEE, DEPARTMENT və PROJECT və s. kimi bir çox masalar var. Əgər biz yalnız EMPLOYEE masasına daxil olsaq, işçilər haqqında yalnız məlumat alacağıq. Bizə onun şöbəsi və ya layihələri haqqında dəqiq təfərrüatlar verməyəcək.
Aşağıda işçilər haqqında çox əsas məlumatlara sahib bir İŞÇİ cədvəli verilmişdir. Bölməsini və ya menecerini bilmək istəyiriksə, yalnız şəxsiyyət vəsiqələrini verir. Şöbəsi və ya meneceri ilə bağlı hər hansı bir məlumat əldə etməyəcəyik.

Fərz edək ki, bir işçi barədə bölmə təfərrüatlarını bilmək istəyirik, əvvəlcə həmin işçinin şöbə identifikatorunu ƏMƏKDAŞ cədvəlindən almalıyıq, sonra həmin şəxsiyyət məlumatlarını almaq üçün ŞƏHƏR cədvəlinə getməliyik. Ancaq bu cür gətirmə yorucu olur. Nəticəni bizə bir atışda verməyəcək, işçinin Departament ID-sini saxlamaq üçün bəzi vasitəçi / müvəqqəti yaddaş - dəyişənlərə ehtiyac duyacaq və üstəlik tək bir sorğuda yerinə yetirilməyəcəkdir.

Bu, bir işçi üçün şöbə detallarının gətirilməsidir. 10, 100, 1000 və s. Üçün bölmə detallarını axtarmalı olsaq? Səy nədir? Neçə sorğunun işdən çıxarılması lazımdır? Vasitəçi şöbəsi idini tutmaq üçün nə qədər vasitəçi sahəsi ayrılmalıdır? Bölmə təfərrüatlarının birinci sorğuda düzgün işçi ilə uyğunlaşdırıldığı ikinci sorğularla alınan zəmanət nədir?

Bütün bu səylərdən, qarışıqlıqdan və yaddaş itkisindən qaçmaq üçün SQL birləşmə adlı bir texnikadan istifadə edir. Bu texnikada iki və ya daha çoxunu birləşdirir masaları İstənilən nəticəni əldə etmək üçün ümumi sütun vasitəsilə. Başqa sözlə, bütün iştirakçı cədvəllərdən bütün satır və sütunları əldə etmək üçün iki və ya daha çox cədvəl birləşdirilir və ortaq sütunları uyğun gələn son nəticədə yalnız həmin sətirlər saxlanılır.

Yuxarıdakı nümunəmizdə İŞÇİ və BÖLMƏ cədvəlləri işçinin şöbə məlumatlarını almaq üçün birləşdirilmişdir. Burada görülən işlər həm cədvəllərdən bütün sətirləri və sütunları almaq üçün həm cədvəllərin birləşdirilməsi, həm də yalnız ümumi sütunlara uyğun olan sətirlərin saxlanılmasıdır. Bu o deməkdir ki, DEPARTMENT_ID bu iki cədvəli birləşdirən istifadə olunan həm İŞÇİ, həm də BÖLMƏ cədvəlindəki ümumi sütundur. Başqa sözlə, ƏMƏKDAŞ cədvəlindəki DEPARTMENT_ID-dən istifadə edərək həmin departament haqqında daha ətraflı məlumat almaq üçün BÖLMƏ cədvəlinə qoşula bilərik.

Aşağıda hər iki cədvəldəki məlumatların şəkli verilmişdir.

Burada EMPLOYEE_ID = 100, Stevenın DEPARTMENT_ID = 90-a sahib olduğunu görə bilərik. DEPARTMENT_ID = 90 haqqında daha ətraflı məlumat əldə etməyimiz lazımdırsa, DEPARTMENT_ID = 90 qarşı DEPARTMENT cədvəlində əldə edəcəyik. Buna görə Steven şöbəsini əldə etmək üçün qoşulma istifadə edərək sorğu. aşağıdakı kimi olardı:

SELECT dept.*
FROM DEPARTMENTS dept, EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID
AND emp.FIRST_NAME = 'Steven';

Burada Steven üçün iki şöbə detalı aldığımızı görürük. Bunun səbəbi, İŞÇİ masamızda Steven adlı iki fərqli işçimizin olmasıdır. Hər ikisi də fərqli şöbələrdə işləyirlər - 50 və 90. Beləliklə iki şöbə detalı əldə etdik.

Niyə iki şöbə təfərrüatını əldə etdiyimizə dair daha dəqiq olmaq üçün yuxarıdakı SELECT sorğumuza da işçi təfərrüatları əlavə edə bilərik. Nəticəni daha dəqiq və dəqiq edəcəkdir. Lakin sütunların seçilməsi istifadəçinin tələbindən asılıdır.

SELECT emp.EMPLOYEE_ID, emp.first_name, emp.LAST_NAME, dept.*
FROM DEPARTMENTS dept, EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID – Join Condition
AND emp.FIRST_NAME = 'Steven'; – Filtering Condition

İndi niyə iki şöbə detalı aldığımız çox aydındır.
Yuxarıdakı sorğularda 'WHERE' bəndinin cədvəldəki ümumi sütunlardan istifadə edərək iki cədvəli birləşdirmək üçün istifadə olunduğunu qeyd edə bilərik. Sorğuda birləşmələri necə və nə üçün istifadə edirik.

Fərz edək ki, həm işçi stolundakı Steven eyni Departament üçün işləyir. Sorğunun nəticəsi nə olacaq və nə üçün?

SELECT emp.EMPLOYEE_ID, emp.first_name, emp.LAST_NAME, dept.*
FROM DEPARTMENTS dept, EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID
AND emp.FIRST_NAME = 'Steven';

Bunun səbəbi, nəticəni DEPARTMENT_ID-ə əsaslanaraq süzgəcdən keçirməməyimizdir. Burada sorğu Stevenın DEPARTMENT_ID-i və sonra həmin Departament haqqında təfərrüatları almaq üçün yazılmışdır. Beləliklə, sorğu əvvəlcə ƏMƏKDAŞ cədvəlindəki bütün Steven-i gətirəcək və sonra Steven-in bütün şöbələrini alacaq. Burada həm Stevenin şöbəsini eyni sayacaq. Çünki burada həm Stevens fərqlidir və bu səbəbdən də şöbələri fərqli sayılır. Daha aydın olmaq üçün yuxarıdakı sorğu əvvəlcə 'Steven' olan işçilərin bütün DEPARTMENT_ID-i alacaq. Beləliklə, bütün şöbələrin identifikatorlarını dublikatları süzmədən verəcəkdir. Beləliklə DEPARTMENT_ID ilə İŞÇİ masasından iki sıra alırıq. İndi bu DEPARTMET_ID detallarını almaq üçün BÖLMƏ cədvəlinə gətirilib. İki şöbə kimliyimiz olduğundan (eyni olmasına baxmayaraq), BÖLÜM cədvəli iki dəfə ətraflı məlumat almaq üçün soruşulur. Buna görə iki sıra alırıq.

Tutaq ki, işçilərin məlumatlarını SEÇİM siyahısından çıxardıq və yalnız BÖLMƏ detallarını saxladıq. İndi bir sıra göstərəcəyini düşünürsən?

SELECT dept.*
FROM DEPARTMENTS dept, EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID
AND emp.FIRST_NAME = 'Steven';

Cavab YOXDUR. Yenə də təkrarlanan sətirləri göstərəcəkdir. Bunun səbəbi yuxarıdakı eyni səbəbdəndir. Bu o deməkdir ki, satırların ikiqatlığını təyin edən SEÇİM siyahı məlumatları deyil. Bunun hamısı 'emp.FIRST_NAME =' Steven '' filtr şərtinə görədir.

Nəticədə bu cüt satırlardan necə qaça bilərik? Bunun müxtəlif yolları var.

1. Tutaq ki, aşağıdakı sorğu kimi yalnız şöbə detallarını seçirik.

SELECT dept.*
FROM DEPARTMENTS dept, EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID
AND emp.FIRST_NAME = 'Steven';

Buradakı həm Steven BÖLÜM masası eyni şöbədə işlədiyindən, eyni şöbəni iki dəfə alırıq. Beləliklə, burada təkrarlanan satırları silmək üçün DISTINCT bəndindən istifadə edə bilərik. Bu DISTINCT bəndində təkrar bölmələr yalnız bölmələri eyni olduqda silinəcəkdir.

2. Dəqiq nəticəni əldə etmək üçün başqa bir üsul çox dəqiq və konkret sorğu yazmaqdır. Yuxarıda işçi adını istifadə edərək filtr vəziyyətimiz var idi. Ancaq işçi adının unikal olmaması lazımdır. Eyni adlı bir çox işçi ola bilər. Nəticəni müəyyən bir işçi üçün əldə etməyimiz lazım olsa, detallarını İŞÇİ cədvəlindən süzgəcdən keçirərkən çox dəqiq olmalıyıq. Yuxarıda dediyimiz kimi, adını işləyərək işçini düzəldə bilmərik. Hər bir işçi üçün çox unikal olan şəxsiyyət vəsiqəsi istifadə edilərək onun detalları düzgün süzüləcəkdir. Beləliklə, yuxarıdakı sorğuda işçinin adını göstərməkdənsə, işçinin kimliyini göstərsək, daha dəqiq nəticə əldə edəcəyik.

Nəticə barədə daha dəqiq bir şəkildə müəyyənləşdirmək üçün işçilərin təfərrüatlarını seçilmiş siyahıya da daxil edə bilərik. Lakin nəticə dəstimizi dəyişdirməyəcəkdir.

Nəticələrin dəyişdirilməsi həmişə tələbdən asılıdır. Yuxarıda göstərilən hallarda, işçilərin adına əsasən cədvəlləri sorğu etmək istənirsə, təkrarlanan sətirlərdən qorunmaq üçün yalnız DISTINCT istifadə edə bilərik. Ancaq fərqli şöbələrdə çalışsalar, yuxarıdakı iki həll heç bir təsir göstərməyəcəkdir.

Daxili Qoşulma nədir?

Bu birləşmələrin ən sadə formasıdır. Burada iki və ya daha çox cədvəl tələb olunan nəticəni əldə etmək üçün müvafiq cədvəllərdəki ümumi sütun / s əsasında birləşdirilir. Bu birləşmə növü equijoin olaraq da bilinir. Burada iki və ya daha çox cədvəl WHERE bəndində '=' istifadə edərək birləşdirilir. Yalnız hər iki cədvəldə uyğun qeydlər olduqda qeydləri qaytaracaqdır.

Eyni İŞÇİ və BÖLMƏ cədvəlinin nümunəsini nəzərdən keçirin. Tutaq ki, hər bir işçinin çalışdığı şöbə adını görmək istəyirik. Yuxarıda öyrəndik ki, bu hər iki cədvəldə DEPARTMENT_ID-də birləşmə şərtindən istifadə etməklə həyata keçirilir. Burada ƏMƏKDAŞ cədvəlindəki bütün işçiləri sadalamalıyıq və bunun üçün Departament_İD-lərindən asılı olaraq şöbə adını göstərməliyik. yəni;

SELECT emp.EMPLOYEE_ID, emp.first_name, emp.LAST_NAME, 
	dept.DEPARTMENT_ID, dept.DEPARTMENT_NAME
FROM DEPARTMENTS dept, EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID;

Burada ƏMƏKDAŞ cədvəlindəki hər bir işçi üçün bir şöbə kimliyimiz olduğunu və BÖLMƏ cədvəlində uyğun məlumatlara sahib olduğumuzu görə bilərik. ƏMƏKDAŞ cədvəlində yalnız BÖLMƏ cədvəlində detalları olan şöbələrimiz var. Beləliklə, masada daxili birləşməni yerinə yetirdikdə yalnız uyğun satırlar əldə edirik.

Fərz edək ki, BÖLMƏ cədvəlində hələ heç bir işçi təyin olunmayan bəzi şöbələrimiz var. Bu şöbələr daxili sorğu ilə ümumiyyətlə alınmır. Yəni cədvəlləri birləşdirdiyimiz zaman, hər iki cədvəldəki İdarəetmə altından alınacaq. Onları hər iki cədvəldə taparsa, nəticəni SEÇİM siyahı maddələrinə əsasən göstərəcəkdir.

Xarici Qeyd nədir?

Bu, SQL-də başqa bir güclü qoşulma texnikasıdır. Burada az fərqlə daxili birləşmə ilə eyni işləyir. Xarici birləşmə istifadə edildikdə, daxili birləşmələrdə olduğu kimi birləşmə şərtinə uyğun olan bütün qeydləri siyahıya alır və eyni zamanda cədvəllərdən hər hansı birində uyğun qeydləri olmayan qeydləri siyahıya alır. Burada cədvəlin xarici birləşmə növündən asılı olduğu uyğun olmayan qeydlərin göstərilməsi.

Bölmə cədvəlində işləyən bütün işçiləri çəkmək üçün ƏMƏKDAŞ və BÖLÜM cədvəlləri ilə yuxarıdakı kimi eyni nümunəni nəzərə alsaq, nəticəni aşağıdakı kimi görə bilərik.

SELECT dept.*,emp.*
FROM DEPARTMENTS dept,EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID (+);

OR
SELECT dept.*,emp.*
FROM DEPARTMENTS dept LEFT OUTER JOIN EMPLOYEES emp
ON dept.DEPARTMENT_ID = emp.DEPARTMENT_ID ;

Bu sorğu əvvəlcə şöbələrin cədvəlindəki bütün qeydləri çıxaracaqdır. Sonra İŞÇİLƏR cədvəlindəki bölmələrdə çalışan bütün işçiləri gətirir. İŞÇİLƏR cədvəlindəki bütün uyğun qeydləri siyahıya alır. ŞƏKİLLƏR cədvəlində işçi olmayacaq bir neçə şöbə ola bilər. Bu halda, xarici birləşmə bölmə məlumatlarını və müvafiq əməkdaşlarını NULL olaraq göstərəcəkdir.

Xarici qoşulma bu şəkildə işləyir. Bu qoşulma metodunda qoşulma şərtində iştirak edən cədvəllərdən gələn bütün uyğun qeydlərin əvvəlcə göstəriləcəyini görə bilərik. Sonra ikinci cədvəldə uyğun olmayan bütün qeydlər sıfır kimi qeyd olunur. Bu xarici birləşmələrdəki texnikalardan biridir.

Xarici Qoşulmanın müxtəlif növləri hansılardır?

Xarici qoşulma, qoşulma mərasimində iştirak edən cədvəllərdən və uyğun olmayan qeydlərdən uyğun qeydləri almaq üsuludur. Ancaq uyğun bir qeydə sahib olmayan qeydlərin seçilməsi ya cədvəllərdən biri, ya da hər iki cədvəl arasındadır. Qeydləri cədvəldən çıxarmaq üçün seçilən üsula görə 3 növ xarici birləşmə var - sol xarici birləşmə, sağ xarici birləşmə və tam xarici birləşmə.

  • Sol Xarici Qoşulma: Bu, qoşulma şərtinin solundakı cədvəldəki bütün qeydlərin verildiyi və NULL sağ cədvəlində uyğunluq tapılmayan qeydlərin göstərildiyi xarici birləşmə metodudur. Bu o deməkdir ki, 'A SOL OUTER JOIN B' yazsaq, A-dan bütün qeydlər göstərilir və B cədvəlindəki müvafiq qeydlər onlara qarşı göstərilir. B cədvəlində uyğun olmayan A qeydləri üçün NULL göstərilir.

Bütün şöbəni və işçilərini göstərməli olduğumuz nümunəni nəzərdən keçirin. Burada bütün şöbələri göstərməliyik. O şöbədə işləyən işçilərimiz varsa, o işçiləri göstərmək lazımdır. Bölmə üçün heç bir işçi yoxdursa, bu şöbələri ancaq işçilərini NULL olaraq siyahıya almalıyıq.

SELECT dept.*,emp.*
FROM DEPARTMENTS dept,EMPLOYEES emp
WHERE dept.DEPARTMENT_ID = emp.DEPARTMENT_ID (+);

OR
SELECT dept.*,emp.*
FROM DEPARTMENTS dept LEFT OUTER JOIN EMPLOYEES emp
ON dept.DEPARTMENT_ID = emp.DEPARTMENT_ID ;

Burada BÖLMƏLƏR SOL cədvəl, İŞÇİLƏR isə düzgün cədvəldir. 'LEFT OUTER JOIN' bəndini yazdığımız zaman, bütün cədvəlləri sağ cədvəldəki uyğun qeydləri ilə sol masadan çıxarır. Sağ cədvəldə uyğun qeyd yoxdursa, sütunları üçün NULL-lər göstərilir.

'(+)' İşarəsi istifadə edərək sol xarici qoşma yazmağın başqa bir üsulu var. Sol xarici birləşməni yerinə yetirdikdə, birləşdirmə şərtinin sağ tərəfinə '(+)' yazırıq ki, bütün qeydləri sol masadan çəkirik.

  • Sağ Xarici Qoşulma: Bu, qoşulma şərtinin sağındakı cədvəldəki bütün qeydlərin verildiyi və uyğun cədvəldə NULL matçında tapılmayan qeydlərin göstərildiyi xarici birləşmə metodudur. Bu o deməkdir ki, 'SAĞ OUTER JOIN B' yazsaq, B-dən bütün qeydlər göstərilir və A cədvəlindəki müvafiq qeydlər onlara qarşı göstərilir. A cədvəlində uyğun olmayan B qeydləri üçün NULL göstərilir.

Bütün şöbəni və işçilərini göstərməli olduğumuz eyni nümunəni nəzərdən keçirin. Burada bütün şöbələri göstərməliyik. O şöbədə işləyən işçilərimiz varsa, o işçiləri göstərmək lazımdır. Şöbədə işçi yoxdursa, o şöbəni ancaq işçilərini NULL olaraq siyahıya almalıyıq. Ancaq burada SAĞ xarici qoşulma istifadə edəcəyik. Bu səbəbdən 'SAĞ OUTER JOIN' və ya '(+)' istifadə edəcəyik. '(+)' İşarəsini istifadə edərkən işarənin mövqeyini dəyişdirərək aşağıda göstərildiyi kimi sağ xarici birləşmə olduğunu göstərəcəyik:

SELECT dept.*,emp.*
FROM DEPARTMENTS dept,EMPLOYEES emp
WHERE dept.DEPARTMENT_ID(+) = emp.DEPARTMENT_ID;

OR
SELECT dept.*,emp.*
FROM DEPARTMENTS dept RIGHT OUTER JOIN EMPLOYEES emp
ON dept.DEPARTMENT_ID = emp.DEPARTMENT_ID ;

  • Tam xarici qoşulma: Bu, həm sol həm də sağ xarici birləşmələrin birləşdirildiyi başqa bir xarici birləşmə növüdür. Yəni əvvəlcə hər iki cədvəldəki bütün uyğun qeydlər sadalanır, daha sonra hər iki cədvəldəki bütün qeydlər NULL ilə digər cədvəldəki uyğun olmayan sütunlara verilmişdir.

Tam xarici qoşulma sorğusunu yazmaq üçün '(+)' simvolundan istifadə edə bilmərik. Nəticəni əldə etmək üçün 'FULL OUTER JOIN' yazmalıyıq. ƏMƏKDAŞLARIMIZ və BÖLMƏLƏRİMİZ nümunəsində, tam xarici birləşdirmə apardığımızda, BÖLMƏLƏRDƏN və İŞÇİLƏRDƏN bütün uyğun qeydləri sadalayacaq və sonra heç bir işçinin olmadığı şöbələrin qalan hissəsini siyahıya alacaq. Sonra hələ heç bir şöbəyə təyin olunmayan bütün işçilərin siyahısını verəcəkdir. Eşleşmeyen cədvəlin sütunları NULL olaraq göstərilir. Aşağıdakı uyğunluq tapılmayan BÖLMƏLƏR və İŞÇİLƏR sütunlarında NULL-lər görə bilərik.

SELECT dept.*,emp.*
FROM DEPARTMENTS dept FULL OUTER JOIN EMPLOYEES emp
ON dept.DEPARTMENT_ID = emp.DEPARTMENT_ID