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

Другие вопросы по тегам