SQL üzrə yeni leksiyamıza xoş gəlmisən! Bu gün ən gözəgörünməz, amma inanılmaz güclü operatorlarla — EXISTS və NOT EXISTS ilə tanış olacağıq. Təsəvvür elə ki, bir kəşfiyyatçı var, iz qoymur, amma dərhal xəbər verir: "Hə, obyekt var" ya da "Yox, burda heç nə yoxdur". Bu operatorlar birbaşa məlumat qaytarmır, amma məntiqi dəqiq yoxlamalar etməyə imkan verir.
Gəlin əsaslardan başlayaq. EXISTS — bu operator sətirlərin mövcudluğunu subquery nəticəsində yoxlayır. Əgər subquery ən azı bir sətir qaytarırsa, EXISTS şərti TRUE olacaq, əks halda — FALSE.
SELECT 1
WHERE EXISTS (
SELECT *
FROM students
WHERE grade > 3.5
);
Gördüyün kimi, bizi subquery-nin öz məlumatları maraqlandırmır, sadəcə belə sətirlərin olub-olmaması maraqlıdır. Əgər ən azı bir sətir şərtə uyğundursa, sorğu 1 qaytarır.
EXISTS sintaksisi
EXISTS sintaksisi çox sadədir:
SELECT kolonlar
FROM cədvəl
WHERE EXISTS (
SELECT 1
FROM başqa_cədvəl
WHERE şərt
);
İzah:
EXISTSiçindəki subquery istənilən sorğu ola bilər.- Məhz subquery-nin nəticəsi müəyyən edir ki,
TRUEyaFALSEqaytarılacaq.
Nümunə: 4-dən yuxarı qiymət alan tələbə var?
Təsəvvür elə students cədvəli var:
| id | name | grade |
|---|---|---|
| 1 | Otto | 3.2 |
| 2 | Anna | 4.7 |
| 3 | Dan | 5.0 |
| 4 | Lina | 2.9 |
Güman edək ki, yoxlamaq istəyirik, 4-dən yuxarı qiymət alan tələbə var ya yox. Aşağıdakı sorğunu istifadə edirik:
SELECT 'Yüksək bal alan tələbələr var!'
WHERE EXISTS (
SELECT 1
FROM students
WHERE grade > 4
);
Nəticə:
Yüksək bal alan tələbələr var!
Niyə EXISTS IN-dən daha sürətlidir?
EXISTS-in əsas üstünlüyü ondadır ki, ilk uyğunluğu tapanda subquery-nin icrasını dayandırır. Yəni, əgər bizə sadəcə məlumatın mövcudluğu lazımdırsa, EXISTS çox effektiv ola bilər.
Məsələn, təsəvvür elə students cədvəlində milyonlarla sətir var, amma biz sadəcə bir uyğunluq axtarırıq (grade > 4). SQL ilk uyğun sətiri tapanda sorğunu bitirir.
NOT EXISTS istifadəsi
İndi isə NOT EXISTS-dən danışaq. Bu operator EXISTS-in əksi kimi işləyir. Əgər subquery heç bir sətir qaytarmırsa, TRUE qaytarır.
Nümunə: qiyməti olmayan tələbələri tapmaq (NULL)
Güman edək ki, cədvəldə qiyməti olmayan tələbələr var:
| id | name | grade |
|---|---|---|
| 1 | Otto | NULL |
| 2 | Anna | 4.7 |
| 3 | Dan | 5.0 |
| 4 | Lina | NULL |
Qiyməti olmayan bütün tələbələri seçmək istəyirik. NOT EXISTS istifadə edirik:
SELECT *
FROM students s
WHERE NOT EXISTS (
SELECT 1
FROM students
WHERE grade IS NOT NULL
AND id = s.id
);
Nəticə:
| id | name | grade |
|---|---|---|
| 1 | Otto | NULL |
| 4 | Lina | NULL |
EXISTS və IN müqayisəsi
Bəzən elə gəlir ki, EXISTS və IN eyni işi görür. İlk baxışda — bəli, amma incəliklər var. Xüsusilə hardasa NULL varsa. Onda IN-in davranışı gözlənilməz ola bilər, EXISTS isə köməyə gəlir.
Gəlin nümunəyə baxaq.
courses cədvəli (keçmək mümkün olan kurslar):
| course_id | name |
|---|---|
| 1 | Riyaziyyat |
| 2 | Tarix |
Və tələbələr:
| student_id | name |
|---|---|
| 1 | Alex Lin |
| 2 | Anna Song |
| 3 | Maria Chi |
| 4 | Dan Seth |
| 5 | Shadow Moon |
enrollments cədvəli (kim hansı kursa yazılıb):
| student_id | course_id |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | NULL |
Kurs adlarını seçmək istəyirik, hansına ki, kimsə yazılıb. Sadə görünür.
IN ilə istifadə:
SELECT name
FROM courses
WHERE course_id IN (
SELECT course_id
FROM enrollments
);
İlk baxışda hər şey işləməlidir. Amma əgər enrollments-də NULL varsa courseid-də, Maria Chi-də olduğu kimi, IN heç nə qaytarmaya bilər! Çünki NULL subquery-ni "müəyyən olmayan" edir və SQL çaşır: bəlkə NULL elə axtardığımız courseid-dir?
EXISTS ilə istifadə:
SELECT name
FROM courses c
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE c.course_id = e.course_id
);
Amma EXISTS yoxlayır: "Ən azı bir sətir var ki, course_id üst-üstə düşür?" — vəssalam. NULL varsa belə, onu narahat etmir, çünki konkret uyğunluq axtarır, dəyər siyahısı yox.
Nəticə: əgər subquery-də NULL ola bilərsə, sürpriz yaşamamaq üçün EXISTS istifadə elə.
Real tapşırıqlardan nümunələr
students cədvəli:
| id | name |
|---|---|
| 1 | Alex Lin |
| 2 | Anna Song |
| 3 | Maria Chi |
| 4 | Dan Seth |
| 5 | Shadow Moon |
enrollments cədvəli:
| student_id | course_id |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | NULL |
Nümunə 1. Kurslara yazılan tələbələr
Kimlərsə artıq hardasa "görünüb" — kursa yazılıb (Maria Chi kimi qəribə də olsa):
SELECT name
FROM students s
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE s.id = e.student_id
);
Nəticə:
Alex Lin
Anna Song
Maria Chi
Əgər tələbə enrollments-də hər hansı formada varsa — seçilir, hətta onun course_id-si aydın olmasa belə.
Nümunə 2. Kursu olmayan tələbələr
İndi isə tapırıq, kimlər hələ sadəcə sistemdə var — amma heç bir kursa yazılmayıb:
SELECT name
FROM students s
WHERE NOT EXISTS (
SELECT 1
FROM enrollments e
WHERE s.id = e.student_id
);
Nəticə:
Dan Seth
Shadow Moon
Görünür, bu ikisi hələ ürəyinə uyğun kurs tapmayıb. Ya da sadəcə yazılmağı unudub :)
Nümunə 3. 5-dən çox qeydiyyat olan kursların seçilməsi
courses cədvəli:
| course_id | name |
|---|---|
| 1 | Riyaziyyat |
| 2 | Tarix |
| 3 | Biologiya |
| 4 | Fəlsəfə |
enrollments cədvəli:
| student_id | course_id |
|---|---|
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 7 | 2 |
| 8 | 2 |
| 9 | 2 |
| 10 | NULL |
Tapmaq istəyirik ki, hansı kurslara beşdən çox tələbə yazılıb. Burda EXISTS sanki soruşur: "Bu kursda ən azı bir qrup qeydiyyat var ki, tələbələrin sayı beşdən çoxdur?"
SELECT name
FROM courses c
WHERE EXISTS (
SELECT 1
FROM enrollments e
WHERE c.course_id = e.course_id
GROUP BY e.course_id
HAVING COUNT(*) > 5
);
Nəticə:
Riyaziyyat
Yalnız "Riyaziyyat" kursuna (course_id = 1) altı tələbə yazılıb. Qalan kurslar hələ o qədər populyar deyil.
EXISTS və NOT EXISTS istifadə edərkən tez-tez edilən səhvlər
- Subquery sintaksisinin düzgün başa düşülməməsi. Həmişə yoxla ki, subquery xarici cədvələ düzgün istinad edir.
NULLyoxlamasının unudulması. HəttaEXISTSistifadə etsən də, bəzənNULLüçün ayrıca işləmə yazmaq lazımdır.- Subquery sahələrində indeksin olmaması. Bu, sorğunun icrasını xeyli ləngidə bilər.
Bu günlük bu qədər! Artıq bilirsən ki, EXISTS və NOT EXISTS ilə məlumatların mövcudluğunu necə yoxlamaq, həmçinin bu operatorların IN ilə fərqlərini. Növbəti leksiyada subquery-lərlə işə davam edəcəyik, SELECT içində onları necə istifadə etməyi və aqreqasiya olunmuş məlumatlarla işləməyi öyrənəcəyik.
GO TO FULL VERSION