İndi gəlin bir az həyatdan danışaq. O tərəfdən ki, ondan qaçmaq olmur: səhvlər. Səhvləri tutmaq, düzəltmək və başa düşmək — data ilə işləməyin vacib hissəsidir. Gəlin baxaq, SQL-də JOIN ilə işləyərkən hansı "qraplilərə" düşürük və onlardan necə yan keçmək olar.
Səhv 1: Birləşmə şərtini unutmaq — dekart hasili yaratmaq
Ən çox rast gəlinən səhv — ON istifadə edərkən birləşmə şərtini göstərməyi unutmaqdır. Bu halda dekart hasili yaranır, yəni birinci cədvəldəki hər sətr ikinci cədvəldəki hər sətr ilə birləşir. Nəticədə, heç bir məna kəsb etməyən və səni çaşdıran tonlarla sətir alırsan.
Misal gətirək. Tutaq ki, bizdə belə cədvəllər var:
Tələbələr (students):
| student_id | name |
|---|---|
| 1 | Otto |
| 2 | Anna |
Kurslar (courses):
| course_id | course_name |
|---|---|
| 101 | Riyaziyyat |
| 102 | Tarix |
İndi ON olmadan sorğu yazaq:
SELECT *
FROM students
JOIN courses;
Nəticə:
| student_id | name | course_id | course_name |
|---|---|---|---|
| 1 | Otto | 101 | Riyaziyyat |
| 1 | Otto | 102 | Tarix |
| 2 | Anna | 101 | Riyaziyyat |
| 2 | Anna | 102 | Tarix |
Bu, real görünmür, düzdür? Bu kabus dekart hasili adlanır.
Necə düzəltmək olar: ON istifadə et, cədvəllərdəki dataların necə bağlı olduğunu göstər.
SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;
Və burada yeni səhv fəsli başlayır...
Axmaqdan qorunma
Bu o qədər yayılmış problemdir ki, PostgreSQL-də JOIN şərtsiz və ON olmadan istifadəsini qadağan ediblər.
Əgər sənə hər sətri hər sətirlə birləşdirmək lazımdırsa, JOIN olmadan belə sintaksis istifadə edə bilərsən:
SELECT *
FROM students, courses;
Başqa bir variant - JOIN ON olmadan işləyəndə:
NATURAL JOINilə — avtomatik olaraq eyni adlı sütunları birləşdirir.USINGilə — birləşdirilən sütunların siyahısını göstərirsən.CROSS JOIN— həmişə şərtsizdir, yəni dekart hasilinin özü.
Səhv 2: Yanlış birləşmə şərti
Bəzən birləşmə şərtini göstərirsən, amma səhv edirsən. Məsələn, cədvəlləri açarlarla yox, əlaqəsiz datalarla birləşdirirsən.
Tutaq ki, tələbələrin və onların yazıldığı kursların siyahısını almaq istəyirik, amma səhv edib əlaqəsiz sahələr üzrə birləşdiririk:
SELECT *
FROM students
JOIN courses
ON students.student_id = courses.course_id;
Belə sorğu səhv nəticə verəcək, çünki student_id və course_id — tamamilə fərqli şeylərdir.
Necə düzəltmək olar: düzgün sütunlardan istifadə etdiyinə əmin ol. Düzgün birləşmə belə ola bilər (əgər tələbələri kurslarla birləşdirən enrollments cədvəlin varsa):
SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Səhv 3: Nəticədə sətrlərin təkrarlanması
Sorğuda bir neçə JOIN əlavə edəndə bəzən sətrlər təkrarlanır. Bu, JOIN olunan cədvəllərdə təkrarlanan yazılar olduqda və ya birləşmə şərtlərini səhv göstərdikdə baş verir.
Tutaq ki, Otto adlı tələbə enrollments cədvəlində eyni kursa iki dəfə yazılıb.
enrollments cədvəlində yazılar:
| student_id | course_id |
|---|---|
| 1 | 101 |
| 1 | 101 |
İndi JOIN ilə sorğu belə nəticə verəcək:
SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Nəticə:
| name | course_name |
|---|---|
| Otto | Riyaziyyat |
| Otto | Riyaziyyat |
Necə düzəltmək olar: birincisi, cədvəllərində təkrarlanan dataların olmadığından əmin ol. İkincisi, əgər bu gözlənilən davranışdırsa, təkrarlananları DISTINCT ilə sil:
SELECT DISTINCT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Səhv 4: INNER JOIN istifadə edəndə sətrlərin itməsi
INNER JOIN yalnız hər iki cədvəldə uyğun gələn sətrləri qaytarır. Əgər bir cədvəldə uyğun dəyər yoxdursa, sətir atılacaq. Yanlış birləşmə növü seçsən, data itirə bilərsən.
Tutaq ki, bizdə hələ heç bir kursa yazılmamış tələbə var:
Tələbələr (students):
| student_id | name |
|---|---|
| 1 | Otto |
| 2 | Anna |
| 3 | Dhany |
Yazılar (enrollments):
| student_id | course_id |
|---|---|
| 1 | 101 |
| 2 | 102 |
İndi INNER JOIN ilə sorğu:
SELECT students.name, courses.course_name
FROM students
JOIN enrollments ON students.student_id = enrollments.student_id
JOIN courses ON enrollments.course_id = courses.course_id;
Nəticə:
| name | course_name |
|---|---|
| Otto | Riyaziyyat |
| Anna | Tarix |
Bəs Dhany haradadır? Əgər kursu olmayan tələbələri də görmək istəyirsənsə, LEFT JOIN istifadə et:
SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id;
Səhv 5: NULL dəyərləri düzgün işləməmək
Əgər cədvəldə boş (NULL) dəyərlər varsa, onlar nəticədən kənarda qala bilər (məsələn, filtrasiya şərtləri istifadə edəndə).
Misal: LEFT JOIN istifadə edirsən, amma sonra WHERE ilə filtrasiya əlavə edirsən.
SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name = 'Riyaziyyat';
İndi kursu olmayan tələbələr nəticəyə düşməyəcək, baxmayaraq ki, LEFT JOIN istifadə etmisən.
Necə düzəltmək olar: əgər kursu olmayan sətrləri də daxil etmək istəyirsənsə, WHERE əvəzinə ON istifadə et və ya əlavə şərt əlavə et:
SELECT students.name, courses.course_name
FROM students
LEFT JOIN enrollments ON students.student_id = enrollments.student_id
LEFT JOIN courses ON enrollments.course_id = courses.course_id
WHERE courses.course_name IS NULL OR courses.course_name = 'Riyaziyyat';
Səhv 6: Birləşmə növləri arasında qarışıqlıq
Hansı birləşmə növünü istifadə edəcəyini qarışdırırsan. Məsələn, RIGHT JOIN istifadə edirsən, halbuki sadəcə cədvəllərin sırasını dəyişməklə LEFT JOIN istifadə etmək olardı.
Qarışıqlıqdan necə qaçmaq olar:
- İmkan varsa,
LEFT JOINistifadə et. Bu, daha intuitivdir. RIGHT JOINlazım olmasın deyə cədvəllərin sırasını dəyiş.
GO TO FULL VERSION