SQL-соединение с NULL-столбцами - PullRequest
7 голосов
/ 12 июня 2010

У меня есть следующие таблицы:

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 в a, я просто использую естественное соединение SELECT b.* FROM b NATURAL JOIN a;, и все в порядке.

Когда a.bid или a.cid имеет значение NULL, я хочу получить каждую строку, где совпадает другой столбец, например если a.bid имеет значение NULL, я хочу, чтобы каждая строка была a.cid=b.cid, если оба имеют значение NULL, я хочу каждый столбец из 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 )

Есть ли лучший способ сделать это?

Ответы [ 3 ]

8 голосов
/ 12 июня 2010

Функция 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 ) )
                )
2 голосов
/ 12 июня 2010

Нет, вот и все.

(я бы вообще перефразировал ISNULL(a.bind) как a.bind IS NULL для соответствия ANSI SQL FWIW.)

1 голос
/ 16 августа 2017

Слишком старый, но вот мои 2 цента, кому-то это может пригодиться

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...