2010-06-12 9 views
6

Mam następujące tabele:SQL Dołącz z NULL kolumn

Table a 
+-------+------------------+------+-----+ 
| Field | Type    | Null | Key | 
+-------+------------------+------+-----+ 
| bid | int(10) unsigned | YES |  | 
| cid | int(10) unsigned | YES |  | 
+-------+------------------+------+-----+
Table b 
+-------+------------------+------+ 
| Field | Type    | Null | 
+-------+------------------+------+ 
| bid | int(10) unsigned | NO | 
| cid | int(10) unsigned | NO | 
| data | int(10) unsigned | NO | 
+-------+------------------+------+

Kiedy chcę, aby zaznaczyć wszystkie wiersze z b gdzie istnieje odpowiednia oferta/cid-pair w a, I po prostu użyj naturalnego połączenia SELECT b.* FROM b NATURAL JOIN a; i wszystko jest w porządku.

Gdy a.bid lub a.cid ma wartość NULL, chcę uzyskać każdy wiersz, w którym pasuje inna kolumna, np. jeśli a.bid ma wartość NULL, chcę, aby każdy wiersz gdzie a.cid=b.cid, jeśli oba są NULL Chcę, aby każda kolumna z b.

Moje naiwne rozwiązanie było to:

SELECT DISTINCT b.* FROM b JOIN a ON (ISNULL(a.bid) OR a.bid=b.bid) AND (ISNULL(a.cid) OR a.cid=b.cid)

Czy istnieje lepszy sposób na to?

Odpowiedz

2

Nie, to prawie wszystko.

(ja generalnie rephrase ISNULL(a.bind) jak a.bind IS NULL za zgodność ANSI SQL FWIW.)

8

Funkcja ISNULL rzeczywistości nie jest zgodny z ANSI. Tak, musisz sprawdzić wartości zerowe w obu kolumnach. Innym sposobem, aby napisać zapytanie będzie:

Select Distinct b.* 
From b 
    Join a 
     On (a.bid = b.bid Or (a.bid Is Null And b.bid Is Null)) 
      And (a.cid = b.cid Or (a.cid Is Null And b.cid Is Null)) 

Jeszcze innym sposobem, który pozwala uniknąć stosowania odrębnych:

Select b.* 
From b 
Where Exists (
       Select 1 
       From a 
       Where (a.bid = b.bid Or (a.bid Is Null And b.bid Is Null)) 
        And (a.cid = b.cid Or (a.cid Is Null And b.cid Is Null)) 
       ) 
+0

b.bid i b.cid nie może być zerowy, więc dodatkowy test jest niepotrzebny, ale podoba mi się drugi przykład bez wyraźnego. – tstenner

+0

@tstenner - Ah. Przegapiłeś, że podałeś, że kolumny w b są niedozwolone. – Thomas

0

zbyt stary, ale tutaj jest moje 2 centy, to może być przydatne dla kogoś

ISNULL (a.cid, 0) = ISNULL (b.cid) i ISNULL (a.bid, 0) = ISNULL (b.bid)