Внутреннее соединение SQL по нулевым значениям - PullRequest
35 голосов
/ 04 февраля 2010

У меня есть Соединение

SELECT * FROM Y
INNER JOIN X ON ISNULL(X.QID, 0) = ISNULL(y.QID, 0) 

Isnull в Соединении, как это делает его медленным.Это как условное соединение.Есть ли что-нибудь подобное?У меня есть много записей, где QID равно нулю

У всех есть обходной путь, который не влечет за собой изменение данных

Ответы [ 7 ]

57 голосов
/ 04 февраля 2010

У вас есть два варианта

INNER JOIN x
   ON x.qid = y.qid OR (x.qid IS NULL AND y.qid IS NULL)

или проще

INNER JOIN x
  ON x.qid IS NOT DISTINCT FROM y.qid
7 голосов
/ 04 февраля 2010

Обязаны ли вы использовать синтаксис внутреннего соединения?

Если нет, вы можете использовать этот альтернативный синтаксис:

SELECT * 
FROM Y,X
WHERE (X.QID=Y.QID) or (X.QUID is null and Y.QUID is null)
5 голосов
/ 18 сентября 2016

В этой статье хорошее обсуждение этой проблемы . Вы можете использовать

SELECT * 
FROM Y
INNER JOIN X ON EXISTS(SELECT X.QID 
                       INTERSECT 
                       SELECT y.QID);
3 голосов
/ 04 февраля 2010

Я почти уверен, что объединение даже не делает то, что вы хотите. Если в таблице a имеется 100 записей с нулевым значением qid и 100 записей в таблице b с нулевым значением qid, объединение в том виде, в котором оно было записано, должно создать перекрестное соединение и дать 10000 результатов для этих записей. Если вы посмотрите на следующий код и запустите примеры, я думаю, что последний, вероятно, больше того набора результатов, который вы намеревались:

create table #test1 (id int identity, qid int)
create table #test2 (id int identity, qid int)

Insert #test1 (qid)
select null
union all
select null
union all
select 1
union all
select 2
union all
select null

Insert #test2 (qid)
select null
union all
select null
union all
select 1
union all
select 3
union all
select null


select * from #test2 t2
join #test1 t1 on t2.qid = t1.qid

select * from #test2 t2
join #test1 t1 on isnull(t2.qid, 0) = isnull(t1.qid, 0)


select * from #test2 t2
join #test1 t1 on 
 t1.qid = t2.qid OR ( t1.qid IS NULL AND t2.qid IS NULL )


select t2.id, t2.qid, t1.id, t1.qid from #test2 t2
join #test1 t1 on t2.qid = t1.qid
union all
select null, null,id, qid from #test1 where qid is null
union all
select id, qid, null, null from #test2  where qid is null
2 голосов
/ 24 июля 2014

Если вы хотите, чтобы в Y.QID были включены нулевые значения, тогда самый быстрый способ -

SELECT * FROM Y LEFT JOIN X ON y.QID = X.QID

Примечание: это решение применимо, только если вам нужны нулевые значения из левой таблицы, т. Е. Y (в вышеприведенном случае).

В противном случае INNER JOIN x ON x.qid IS NOT DISTINCT FROM y.qid правильный способ сделать

0 голосов
/ 11 мая 2016

Вы также можете использовать функцию coalesce . Я проверял это в PostgreSQL , но он также должен работать для MySQL или MS SQL-сервера .

INNER JOIN x ON coalesce(x.qid, -1) = coalesce(y.qid, -1)

Это заменит NULL на -1 перед его оценкой. Следовательно, не должно быть -1 в qid.

0 голосов
/ 04 февраля 2010

Как правило, вы хотите объединить две таблицы, где их столбцы QID оба не null, верно? Однако вы не применяете никаких других условий, таких как два значения QID (что мне кажется странным, но все в порядке). Кажется, что-то простое, как показано ниже (протестировано в MySQL), делает то, что вы хотите:

SELECT * FROM `Y` INNER JOIN `X` ON (`Y`.`QID` IS NOT NULL AND `X`.`QID` IS NOT NULL);

Это дает вам каждую ненулевую строку в Y, присоединенную к каждой ненулевой строке в X.

Обновление: Рико говорит, что он также хочет строки со значениями NULL, почему бы просто:

SELECT * FROM `Y` INNER JOIN `X`;
...