SQL для возврата родительских строк, даже если нет дочерних строк
- редактирование моего вопроса *
У меня есть набор столов. Когда я фильтрую по второй таблице, t2, я все равно хотел бы получить все строки t1.
Сценарий SQL ниже. Я чувствую, что приближаюсь, пока возился, но просто не могу этого сделать.
Короче говоря, мне нужны строки t2, когда это применимо, но все строки t1 с нулями в других столбцах.
Благодарю.
создать таблицу t1 ( id int identity(1,1), parentName varchar(20) null) создать таблицу t2 ( id int identity(1,1), t1id int не нуль, childName varchar(20) ноль) создать таблицу t3 ( id int identity(1,1), t2id int не нуль, gChildName varchar(20) ноль) вставить в t1 (parentName) значения ('bob') вставить в t1 (parentName) значения ( 'john') вставить в t2 (childName, t1id) значения ( 'irving', 1) вставить в t2 (childName, t1id) значения ('parna', 1) вставить в t2 (childName, t1id) значения ( 'mike', 1) Выбрать t1.id, t1.parentName, t2.id, t2.childName из левого внешнего соединения t1 t2 на t2.t1id = t1.id где t2.childName = 'Майк' - то, что я хотел бы это: - 1, Боб, 3, Майк - 2, Джон, ноль, ноль дроп стол T3 дроп стол t2 Drop Table T1
4 ответа
Как уже упоминали другие, вы можете переместить фильтр T3 из общего WHERE
пункт и положить его в JOIN
это препятствует эффективному превращению вашего внешнего соединения в псевдо внутреннее соединение (что происходит потому, что ни один из NULL
значения могут когда-либо соответствовать WHERE
критерии за исключением IS NULL
)
Это очень простое изменение вашего примера кода - просто измените WHERE
в AND
,
create table t1 ( id int identity(1,1), parentName varchar(20) null )
create table t2 ( id int identity(1,1), t1id int not null, childName varchar(20) null )
create table t3 ( id int identity(1,1), t2id int not null, gChildName varchar(20) null )
insert into t1 ( parentName ) values ( 'bob' )
insert into t1 ( parentName ) values ( 'john' )
insert into t2 ( childName, t1id ) values ( 'irving', 1 )
insert into t2 ( childName, t1id ) values ( 'parna', 1 )
insert into t2 ( childName, t1id ) values ( 'mike', 1 )
select
t1.id,
t1.parentName,
t2.id,
t2.childName
from t1
left outer join t2 on t2.t1id = t1.id and t2.childName = 'mike'
drop table t3
drop table t2
drop table t1
Похоже, вы используете левое соединение, но затем отбрасываете строки в соответствии с предложением where. Например:
Select * from Table1 a
left join Table2 b
on a.ID = b.ID
where b.name like 'A%'
удалит все строки из Таблицы 1, где нет совпадений в Таблице 2, даже если вы оставили присоединение (потому что условие where не выполняется, когда b.name имеет значение null).
Чтобы избежать этого, вместо этого поместите ваши условия в объединение, например так:
Select * from Table1 a
left join Table2 b
on a.ID = b.ID and b.name like 'A&'
или добавьте IsNull к предложению where, например:
Select * from Table1 a
left join Table2 b
on a.ID = b.ID
where ISNULL(b.name, 'A') like 'A%'
Изменить: Теперь, когда вы разместили свой запрос, вот конкретный ответ: просто измените "где" на "и", и он вернет результаты, которые вы указали.
select
t1.id,
t1.parentName,
t2.id,
t2.childName
from #t1 t1 left outer join #t2 t2
on t2.t1id = t1.id
and t2.childName = 'mike'
Вы можете просто использовать левое соединение:
Select t1.id,t1.name,t2.id id2,t2.name name2,t3.id id3,t3.name name3
From t1 left join
t2 on t1.id=t2.t1id left join
t3 on t3.t2id=t2.id
Where your condition here
Если вы объединяете 2 или более таблиц и хотите получить результаты из первой, даже если нет совпадения со второй (или третьей и т. Д.), Вам просто нужно изменить соединение на левое соединение. Что-то вроде
ВЫБРАТЬ * ИЗ ТАБЛИЦЫ 1 A
СЛЕДУЮЩЕЕ СОЕДИНЕНИЕ ТАБЛИЦА 2 B НА A.ID=B.RELATEDID