CodeGym /Kurslar /SQL SELF /Əlavə şərtlər JOIN-da: ON ... AND .....

Əlavə şərtlər JOIN-da: ON ... AND ...

SQL SELF
Səviyyə , Dərs
Mövcuddur

Artıq bilirsən ki, cədvəlləri JOIN ilə birləşdirmək olur. Amma real həyatda sadəcə açarların uyğun gəlməsi bəzən kifayət etmir. Tez-tez belə bir məsələ çıxır: məlumatları yalnız əlavə bir kriteriyaya uyğun gələndə birləşdirmək — məsələn, yalnız aktiv qeydlər, yalnız cari ilin məlumatları və ya yalnız tamamlanmış sifarişlər.

Və bax, burada ON konstruksiyasını AND ilə genişləndirmək işə yarayır.

JOIN ... ON-da əlavə şərtlər birləşmədə hansı sətrlərin iştirak edəcəyinə tam nəzarət etməyə imkan verir, hələ SQL nəticəni qurmağa başlamamışdan əvvəl. Bu sorğunu belə edir:

  • Daha sürətli (daha az sətir JOIN-dan keçir),
  • Daha dəqiq (filtrasiya birləşmə mərhələsində baş verir),
  • Daha proqnozlaşdırıla bilən LEFT JOIN ilə işləyəndə (WHERE-da filtrasiyadan fərqli olaraq).

Nümunə: Yalnız kurslara aktiv yazılanlar

Tutaq ki, enrollments cədvəlində tələbənin iştirak statusu var: active, dropped, pending.

students cədvəli:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

enrollments cədvəlini yeniləyək:

student_id course_id status
1 101 active
1 103 active
2 102 dropped
3 101 active

courses cədvəli:

id name
101 Mathematics
102 Physics
103 Computer Science

İndi istəyirik ki, yalnız aktiv kursları olan tələbələri əldə edək:

SELECT 
    students.name AS student_name,
    courses.name AS course_name
FROM students 
INNER JOIN enrollments 
    ON students.id = enrollments.student_id
    AND enrollments.status = 'active'
INNER JOIN courses 
    ON enrollments.course_id = courses.id;

Nəticə:

student_name course_name
Otto Song Mathematics
Otto Song Computer Science
Alex Lin Mathematics

Burada AND enrollments.status = 'active' ON-un içində əlavə etdik ki, birləşmə yalnız aktiv qeydlərə görə baş versin, nəticədən sonra filtrasiya olmasın.

Niyə WHERE yox?

Belə də yazmaq olardı:

...
WHERE enrollments.status = 'active'

Amma bu LEFT JOIN-da fərqli davranır. WHERE-da filtrasiya uyğunluq olmayan sətrləri (NULL) silir və nəticədə LEFT JOININNER JOIN-a çevirir.

Amma AND enrollments.status = 'active' şərti ON-un içində birləşən sətrləri dərhal məhdudlaşdırır — birləşməyə ümumiyyətlə hansı sətrlərin düşəcəyinə nəzarət edir, sadəcə nəticəni sonra filtrasiya etmir.

Bu yanaşma xüsusilə vacibdir, əgər istəyirsənsə ki, bir cədvəldə olan sətrlər qalsın, hətta digər cədvəldə uyğun dəyər olmasa belə (bu, hesabat və analitikada tez-tez olur).

ON ... AND ... istifadəsinə başqa nümunələr

students cədvəli:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

enrollments cədvəli:

student_id course_id status enrolled_at
1 101 active 2025-02-01
1 103 active 2025-03-05
2 102 dropped 2024-05-15
3 101 active 2025-03-12

courses cədvəli:

id name
101 Math
102 Physics
103 CS

Nümunə: yalnız cari ilin kursları

SELECT
    students.name,
    courses.name,
    enrollments.enrolled_at
FROM students
JOIN enrollments
    ON students.id = enrollments.student_id
    AND EXTRACT(YEAR FROM enrollments.enrolled_at) = EXTRACT(YEAR FROM CURRENT_DATE)
JOIN courses
    ON enrollments.course_id = courses.id;

Burada yalnız cari ilə aid olan qeydləri birləşdiririk.

name name enrolled_at
Otto Song Math 2025-02-01
Otto Song CS 2025-03-05
Alex Lin Math 2025-03-12

Nümunə: dəyərə görə istisna

JOIN enrollments
    ON students.id = enrollments.student_id
    AND enrollments.status != 'dropped'

Çıxarılmış tələbələri birləşmə mərhələsində istisna edirik, nəticədən sonra yox.

name name
Otto Song Math
Otto Song CS
Alex Lin Math

Şərt ON-un içində olanda, PostgreSQL birləşmə planını optimallaşdıra və daha az sətir işləyə bilər. Bu, böyük həcmli məlumatlarda xüsusilə vacibdir. Daxili filtrasiya JOIN-dan sonra "təmizləmə"dən daha effektivdir.

JOIN ONyalnız açarlar üçün deyil

Çoxları düşünür ki, ON — sadəcə id = id-dir. Əslində ora əlavə etmək olar:

  • Logical operatorlar: AND, OR, NOT
  • Müqayisələr: >, <, <>, BETWEEN, IN
  • Expressions: EXTRACT, DATE_TRUNC, COALESCE, NULLIF

Hamısını birləşdiririk

students cədvəli:

id name
1 Otto Song
2 Maria Chi
3 Alex Lin

faculties cədvəli:

id name
10 Engineering
20 Natural Sciences
30 ← ad yoxdur (NULL)

courses cədvəli:

id name teacher faculty_id
101 Math Liam Park 10
102 Physics Chloe Zhang 20
103 CS Noah Kim 10
104 PE Ava Chen 30

enrollments cədvəli:

student_id course_id status
1 101 active
1 103 active
2 102 dropped
3 101 active
3 104 active
SELECT
    s.name AS student_name,
    c.name AS course_name,
    f.name AS faculty_name
FROM students s
JOIN enrollments e
    ON s.id = e.student_id
    AND e.status = 'active'
JOIN courses c
    ON e.course_id = c.id
    AND c.name != 'Fizkultura'
JOIN faculties f
    ON c.faculty_id = f.id
    AND f.name IS NOT NULL;

Burada eyni anda filtrasiya edirik:

  • Aktiv qeydlərə,
  • "Fizkultura"dan başqa kurslara,
  • Adı olan fakültələrə.

Sorğunun nəticəsi:

student_name course_name faculty_name
Otto Song Math Engineering
Otto Song CS Engineering
Alex Lin Math Engineering

Ümid edirəm bu leksiya xoşuna gəldi. Sorğularda bir neçə JOIN və filtr tez-tez istifadə edəcəksən. Demək olar ki, həmişə :)

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION