У меня есть следующие таблицы:
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 | +-------+------------------+------+
Когда я хочу выбрать все строки из b, где существует соответствующий bid/cid-pair в a, я просто использую естественное соединение SELECT b.* FROM b NATURAL JOIN a;
и все прекрасно.
Когда a.bid или a.cid являются ПУСТЫМИ, я хочу получить каждую строку, где другой столбец соответствует, например, если a.bid является ПУСТЫМ, я хочу каждую строку где a.cid=b.cid
, если оба являются ПУСТЫМИ, я хочу каждый столбец от b.
Мое наивное решение было этим:
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 )
Там какой-либо лучший путь к к этому?
Нет, это все.
(Я бы обычно перефразировал ISNULL (a.bind)
как a.bind IS NULL
для соответствия FWIW ANSI SQL.)
Функция ISNULL на самом деле не соответствует стандарту ANSI. Да, вам нужно проверять нули в обоих столбцах. Другой способ написать запрос был бы следующим:
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 ) )
Еще один способ, который позволяет избежать использования Distinct:
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 ) )
)