Supposons que j'ai ces tables
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')
et je voudrais joindre les tables sur les colonnes id
et le résultat devrait être comme ceci:
id name blockingName
----------- -------------------- --------------------
1 bad name qa bug
2 bad condition NULL
3 about box NULL
Cela signifie: je voudrais retourner toutes les lignes de #bug, il ne devrait y avoir que la valeur 'qa bug' dans la colonne 'blockingName' ou NULL (si aucune ligne correspondante dans #blocking n'a été trouvée)
Ma sélection naïve était comme ça:
select * from #bug t1
left join #blocking t2 on t1.id = t2.id
where t2.name is null or t2.name = 'qa bug'
mais cela ne fonctionne pas, car il semble que la condition soit d'abord appliquée à la table #blocking, puis elle est jointe.
Quelle est la solution la plus simple/typique pour ce problème? (J'ai une solution avec la sélection imbriquée, mais j'espère qu'il y a quelque chose de mieux)
Mettez simplement les critères "qa bug" dans la jointure:
select t1.*, t2.name from #bug t1
left join #blocking t2 on t1.id = t2.id AND t2.name = 'qa bug'
la sélection correcte est:
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
Il semble que vous ne souhaitiez sélectionner qu'une seule ligne parmi #blocking
et joignez-le à #bug
. Je ferais:
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
select *
from #bug t1
left join #blocking t2 on t1.id = t2.id and t2.name = 'qa bug'
assurez-vous que la requête interne ne renvoie qu'une seule ligne. Vous devrez peut-être ajouter un top 1 s'il en renvoie plus d'un.
select
t1.id, t1.name,
(select b.name from #blocking b where b.id=t1.id and b.name='qa bug')
from #bug t1
Voici une démo: 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
En ajoutant la clause "blocking.name" sous la jointure externe gauche, plutôt que dans le where, vous indiquez qu'elle doit également être considérée comme "externe" ou facultative. Lorsqu'elle fait partie de la clause where, elle est considérée comme obligatoire (c'est pourquoi les valeurs nulles ont été filtrées).
BTW - sqlfiddle.com est mon site.