Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Menggunakan IS NULL atau IS NOT NULL pada kondisi join - Pertanyaan teori

Contoh dengan tabel A dan B:

 A (parent)       B (child)    
============    =============
 id | name        pid | name 
------------    -------------
  1 | Alex         1  | Kate
  2 | Bill         1  | Lia
  3 | Cath         3  | Mary
  4 | Dale       NULL | Pan
  5 | Evan  

Jika Anda ingin menemukan orang tua dan anak-anak mereka, lakukan INNER JOIN :

SELECT id,  parent.name AS parent
     , pid, child.name  AS child

FROM
        parent  INNER JOIN  child
  ON   parent.id     =    child.pid

Hasilnya adalah setiap kecocokan parent id dari tabel kiri dan child pid dari tabel kedua akan ditampilkan sebagai baris dalam hasil:

+----+--------+------+-------+
| id | parent | pid  | child | 
+----+--------+------+-------+
|  1 | Alex   |   1  | Kate  |
|  1 | Alex   |   1  | Lia   |
|  3 | Cath   |   3  | Mary  |
+----+--------+------+-------+

Sekarang, di atas tidak menunjukkan orang tua tanpa anak (karena id mereka tidak memiliki kecocokan dengan id anak, jadi apa yang Anda lakukan? Anda melakukan outer join sebagai gantinya. Ada tiga jenis outer join, kiri, kanan dan gabungan luar penuh. Kita membutuhkan yang kiri karena kita menginginkan baris "ekstra" dari tabel kiri (induk):

SELECT id,  parent.name AS parent
     , pid, child.name  AS child

FROM
        parent  LEFT JOIN  child
  ON   parent.id    =    child.pid

Hasilnya selain pertandingan sebelumnya, semua orang tua yang tidak memiliki kecocokan (baca:belum punya anak) juga ditampilkan:

+----+--------+------+-------+
| id | parent | pid  | child | 
+----+--------+------+-------+
|  1 | Alex   |   1  | Kate  |
|  1 | Alex   |   1  | Lia   |
|  3 | Cath   |   3  | Mary  |
|  2 | Bill   | NULL | NULL  |
|  4 | Dale   | NULL | NULL  |
|  5 | Evan   | NULL | NULL  |
+----+--------+------+-------+

Di mana semua NULLs . itu? berasal dari? Yah, MySQL (atau RDBMS lain yang mungkin Anda gunakan) tidak akan tahu apa yang harus diletakkan di sana karena orang tua ini tidak memiliki kecocokan (anak), jadi tidak ada pid atau child.name untuk mencocokkan dengan orang tua itu. Jadi, ini menempatkan non-nilai khusus yang disebut NULLs .

Maksud saya adalah bahwa NULLs ini dibuat (dalam kumpulan hasil) selama LEFT OUTER JOIN .

Jadi, jika kita ingin menampilkan hanya orang tua yang TIDAK memiliki anak, kita dapat menambahkan WHERE child.pid IS NULL ke LEFT JOIN di atas. The WHERE klausa dievaluasi (diperiksa) setelah JOIN dilakukan. Jadi, jelas dari hasil di atas bahwa hanya tiga baris terakhir tempat pid adalah NULL akan ditampilkan:

SELECT id,  parent.name AS parent
     , pid, child.name  AS child

FROM
        parent  LEFT JOIN  child
  ON   parent.id    =    child.pid

WHERE child.pid IS NULL

Hasil:

+----+--------+------+-------+
| id | parent | pid  | child | 
+----+--------+------+-------+
|  2 | Bill   | NULL | NULL  |
|  4 | Dale   | NULL | NULL  |
|  5 | Evan   | NULL | NULL  |
+----+--------+------+-------+

Sekarang, apa yang terjadi jika kita memindahkan IS NULL periksa dari WHERE untuk bergabung dengan ON klausa?

SELECT id,  parent.name AS parent
     , pid, child.name  AS child

FROM
        parent  LEFT JOIN  child
  ON   parent.id    =    child.pid
  AND  child.pid IS NULL

Dalam hal ini database mencoba untuk menemukan baris dari dua tabel yang cocok dengan kondisi ini. Yaitu, baris di mana parent.id = child.pid DAN child.pid IN NULL . Tetapi ia tidak dapat menemukan tidak ada kecocokan seperti itu karena tidak ada child.pid bisa sama dengan sesuatu (1, 2, 3, 4 atau 5) dan NULL pada saat yang sama!

Jadi, syaratnya:

ON   parent.id    =    child.pid
AND  child.pid IS NULL

setara dengan:

ON   1 = 0

yang selalu False .

Jadi, mengapa mengembalikan SEMUA baris dari tabel kiri? Karena ini adalah KIRI GABUNG! Dan gabungan kiri mengembalikan baris yang cocok (tidak ada dalam kasus ini) dan juga baris dari tabel kiri yang tidak cocok centang (semua dalam kasus ini ):

+----+--------+------+-------+
| id | parent | pid  | child | 
+----+--------+------+-------+
|  1 | Alex   | NULL | NULL  |
|  2 | Bill   | NULL | NULL  |
|  3 | Cath   | NULL | NULL  |
|  4 | Dale   | NULL | NULL  |
|  5 | Evan   | NULL | NULL  |
+----+--------+------+-------+

Saya harap penjelasan di atas jelas.

Sidenote (tidak terkait langsung dengan pertanyaan Anda):Mengapa tidak Pan muncul di salah satu GABUNG kami? Karena pid-nya adalah NULLs dan NULL dalam logika SQL (tidak umum) tidak sama dengan apa pun sehingga tidak dapat cocok dengan id induk mana pun (yaitu 1,2,3,4 dan 5). Bahkan jika ada NULL di sana, itu tetap tidak cocok karena NULLs tidak sama dengan apa pun, bahkan NULLs sendiri (itu logika yang sangat aneh, memang!). Itu sebabnya kami menggunakan cek khusus IS NULL dan bukan = NULL periksa.

Jadi, akankah Pan muncul jika kita melakukan RIGHT JOIN ? Ya, tentu saja! Karena RIGHT JOIN akan menampilkan semua hasil yang cocok (INNER JOIN pertama yang kami lakukan) ditambah semua baris dari tabel RIGHT yang tidak cocok (yang dalam kasus kami adalah satu, (NULL, 'Pan') baris.

SELECT id,  parent.name AS parent
     , pid, child.name  AS child

FROM
        parent  RIGHT JOIN  child
  ON   parent.id     =    child.pid

Hasil:

+------+--------+------+-------+
| id   | parent | pid  | child | 
+---------------+------+-------+
|   1  | Alex   |   1  | Kate  |
|   1  | Alex   |   1  | Lia   |
|   3  | Cath   |   3  | Mary  |
| NULL | NULL   | NULL | Pan   |
+------+--------+------+-------+

Sayangnya, MySQL tidak memiliki FULL JOIN . Anda dapat mencobanya di RDBMS lain, dan itu akan menunjukkan:

+------+--------+------+-------+
|  id  | parent | pid  | child | 
+------+--------+------+-------+
|   1  | Alex   |   1  | Kate  |
|   1  | Alex   |   1  | Lia   |
|   3  | Cath   |   3  | Mary  |
|   2  | Bill   | NULL | NULL  |
|   4  | Dale   | NULL | NULL  |
|   5  | Evan   | NULL | NULL  |
| NULL | NULL   | NULL | Pan   |
+------+--------+------+-------+


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Membuat pemicu untuk hanya berjalan ketika tabel baru sedang dibuat

  2. cara mengubah ukuran kolom

  3. Oracle instantclient DYLD_LIBRARY_PATH kesalahan

  4. SQL Server:bagaimana cara meniru permintaan Oracle keep density_rank?

  5. Lampiran di Aplikasi Oracle R12