Оставить соединение с условием - PullRequest
17 голосов
/ 06 февраля 2012

Предположим, у меня есть эти таблицы

create table bug (
    id int primary key, 
    name varchar(20)
)
create table blocking (
    pk int primary key,
    id int, 
    name varchar(20)
)

insert into bug values (1, 'bad name')
insert into bug values (2, 'bad condition')
insert into bug values (3, 'about box')
insert into blocking values (0, 1, 'qa bug')
insert into blocking values (1, 1, 'doc bug')
insert into blocking values (2, 2, 'doc bug')

, и я хотел бы объединить таблицы в столбцах id, и результат должен выглядеть следующим образом:

id          name                 blockingName
----------- -------------------- --------------------
1           bad name             qa bug
2           bad condition        NULL
3           about box            NULL

Это означает: Я хотел бы вернуть все строки из #bug, в столбце blockingName должно быть только значение qa bug или NULL (если не найдено подходящей строки в #blocking)


Мой наивныйselect был похож на это:

select * from #bug t1 
    left join #blocking t2 on t1.id = t2.id
    where t2.name is null or t2.name = 'qa bug'

, но это не работает, потому что кажется, что условие сначала применяется к таблице #blocking, а затем присоединяется.

Что является самым простым /Типичное решение этой проблемы?(У меня есть решение с помощью вложенного выбора, но я надеюсь, что есть что-то лучше)

Ответы [ 6 ]

41 голосов
/ 06 февраля 2012

Просто вставьте критерии "ошибка" в объединение:

select t1.*, t2.name from #bug t1 
left join #blocking t2 on t1.id = t2.id AND t2.name = 'qa bug'
3 голосов
/ 06 февраля 2012

правильный выбор:

create table bug (
id int primary key, 
name varchar(20)
)
insert into bug values (1, 'bad name')
insert into bug values (2, 'bad condition')
insert into bug values (3, 'about box')

CREATE TABLE blocking
(
pk int IDENTITY(1,1)PRIMARY KEY ,
id int, 
name varchar(20)
)
insert into blocking values (1, 'qa bug')
insert into blocking values (1, 'doc bug')
insert into blocking values (2, 'doc bug')


select 
t1.id, t1.name,
(select  b.name from blocking b where b.id=t1.id and b.name='qa bug')
from bug t1 
2 голосов
/ 06 февраля 2012
select * 
from #bug t1 
left join #blocking t2 on t1.id = t2.id and t2.name = 'qa bug'
2 голосов
/ 06 февраля 2012

Похоже, вы хотите выбрать только одну строку из #blocking и присоединить ее к #bug. Я бы сделал:

select t1.id, t1.name, t2.name as `blockingName` 
from `#bug` t1
left join (select * from `#blocking` where name = "qa bug") t2
on t1.id = t2.id
1 голос
/ 06 февраля 2012

Вот демонстрация: http://sqlfiddle.com/#!2/414e6/1

select
  bug.id,
  bug.name,
  blocking.name as blockingType
from
  bug
    left outer join blocking on
      bug.id = blocking.id AND
      blocking.name = 'qa bug'
order by
  bug.id

Добавляя предложение «blocking.name» под левым внешним соединением, а не где, вы указываете, что оно также должно рассматриваться как «внешнее»."или необязательно.Являясь частью предложения where, оно считается обязательным (именно поэтому нулевые значения были отфильтрованы).

BTW - sqlfiddle.com - мой сайт.

1 голос
/ 06 февраля 2012

убедитесь, что внутренний запрос возвращает только одну строку. Возможно, вам придется добавить топ 1, если он возвращает более одного.

select 
t1.id, t1.name,
(select  b.name from #blocking b where b.id=t1.id and b.name='qa bug')
from #bug t1 
...