web-dev-qa-db-ja.com

条件付き左結合

これらのテーブルがあるとします

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'の値しかありません(一致する行が#blockingに見つからなかった場合)。


私の素朴な選択はこのようなものでした:

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

しかし、これは機能しません。条件が最初に#blockingテーブルに適用されてから結合されるようです。

この問題の最も簡単で典型的な解決策は何ですか? (私はネストされた選択を使用した解決策がありますが、もっと良いものがあることを願っています)

21
stej

"qaバグ"基準を結合に入れるだけです。

select t1.*, t2.name from #bug t1 
left join #blocking t2 on t1.id = t2.id AND t2.name = 'qa bug'
42
samjudson

正しい選択は:

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 
3
ludek janicek

#blockingから1行だけを選択し、それを#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
2
Matt Fenwick
select * 
from #bug t1 
left join #blocking t2 on t1.id = t2.id and t2.name = 'qa bug'
2
StevieG

内部クエリが1行のみを返すことを確認してください。複数を返す場合は、上位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 
1
Diego

これがデモです: 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

Whereではなく、左外部結合の下に "blocking.name"句を追加することで、 "外部"またはオプションと見なす必要があることを示します。 where句の一部である場合、それは必須と見なされます(これが、null値が除外されていた理由です)。

ところで、sqlfiddle.comは私のサイトです。

1
Jake Feasel