Выберите Родитель с нулевым, а не нулевым дочерним элементом

Учитывая 3 таблицы, такие как:

[Table_Main]   ---->   [Table_Sub]   ---->   [Table_Prop]
                1-N                   0-N

Я хочу выбрать элемент в [Table_Main], который :
- Иметь несколько [Table_Sub].
- со строками [Table_Sub], в которых есть и [Table_Prop], и нет.

Чтобы выбрать это значение, я использую:

SELECT      Table_Main.Field_ID
FROM        Table_Main
    INNER JOIN  Table_Sub       on  Table_Main.Field_ID  =  Table_Sub.Table_Main_Field_ID
    LEFT JOIN   Table_Prop      on  Table_Sub.Field_ID   =  Table_Prop.Table_Sub_Field_ID

Если мы переименуем таблицу Family, Child и Pet. Мне нужна семья, где у некоторых детей есть домашние животные, а у некоторых детей нет.

Семья: идентификатор, имя

1, Foo      -- Family with 2 childs, one of them has a pet
2, Bar      -- Family with 2 childs, 0 pet
3, Abc      -- Family with 2 childs, both have pet

Ребенок: идентификатор, Family_Id, имя

1, 1, John      -- Child of Foo
2, 1, Joe       -- Child of Foo
3, 2, Jane
4, 2, Jessica
5, 3, XXX
6, 3, YYY

Питомец: Id, Child_Id, Имя

1, 2, FooBar    -- Joe's pet
2, 5, Huey 
3, 6, Dewey  

Ожидаемый результат: 1, Фу

Семья с менее чем 2 детьми исключена из примера, если они могут удовлетворить оба ограничения:
- Есть ребенок с домашним животным
- Имеет ребенка без домашних животных.


Table Creation :
CREATE TABLE Family(
    1    INTEGER  NOT NULL PRIMARY KEY
    ,Foo  VARCHAR(20) NOT NULL
);
INSERT INTO Family(1,Foo) VALUES (1,'Foo');
INSERT INTO Family(1,Foo) VALUES (2,'Bar');
INSERT INTO Family(1,Foo) VALUES (3,'Abc');


CREATE TABLE Child(
   Id        INTEGER  NOT NULL PRIMARY KEY 
  ,Family_Id INTEGER  NOT NULL
  ,Name      VARCHAR(20) NOT NULL
);
INSERT INTO Child(Id,Family_Id,Name) VALUES (1,1,'John');
INSERT INTO Child(Id,Family_Id,Name) VALUES (2,1,'Joe');
INSERT INTO Child(Id,Family_Id,Name) VALUES (3,2,'Jane');
INSERT INTO Child(Id,Family_Id,Name) VALUES (4,2,'Jessica');
INSERT INTO Child(Id,Family_Id,Name) VALUES (5,3,'XXX');
INSERT INTO Child(Id,Family_Id,Name) VALUES (6,3,'YYY');


CREATE TABLE Pet(
   Id       INTEGER  NOT NULL PRIMARY KEY 
  ,Family_I INTEGER  NOT NULL
  ,Name     VARCHAR(20) NOT NULL
);
INSERT INTO Pet(Id,Family_Id,Name) VALUES (1,2,'FooBar');
INSERT INTO Pet(Id,Family_Id,Name) VALUES (2,5,'Huey');
INSERT INTO Pet(Id,Family_Id,Name) VALUES (3,6,'Dewey');

Образцы данных и ожидаемые результаты помогут другим понять вашу цель.

Larnu 08.04.2019 15:16

Вопрос тоже не помешал бы.

HABO 08.04.2019 15:16

Демонстрационные данные лучше всего использовать как DDL + ДМЛ. Пожалуйста, редактировать ваш вопрос, чтобы включить его, вашу текущую попытку и желаемые результаты. Для получения дополнительной информации прочитай это.

Zohar Peled 08.04.2019 15:19

@ZoharPeled, хотя я достаточно упростил вопрос, чтобы сделать его ясным, общим и независимым от данных. Но чтение «и» как не исключающего приводит людей к мысли, что я пропустил группу.

xdtTransform 08.04.2019 16:09

Я не знаю, почему ты обращаешься ко мне. Я не сказал, что вопрос не простой, я только сказал, что для этого нужны образцы данных. IMO, если вы уже удосужились отредактировать свой вопрос с помощью образца данных, вам следовало приложить дополнительные усилия и предоставить его как DDL + DML.

Zohar Peled 08.04.2019 16:13

Извините за пинг, я могу пинговать только одного пользователя на комментарий, я взял последний. Я предоставлю скрипку sql в следующий раз. Я просто не люблю DDL+DML. в простой вопрос, потому что они едят, чтобы занять место без всякой причины.

xdtTransform 08.04.2019 16:22

Скрипка - это хорошо и все такое, но хороший вопрос самодостаточен - по тем же причинам, по которым ответы только на ссылки имеют низкое качество: ссылки не всегда доступны. Для получения дополнительной информации: Почему я должен предоставлять MCVE для того, что мне кажется очень простым SQL-запросом?

Zohar Peled 16.04.2019 11:40

@ZoharPeled, Done, было отложено из-за того, что SqlFiddle все еще не работает. Поэтому я создаю регулярное выражение для анализа и вывода скрипта. Я понимаю правила, я понимаю, почему до сих пор считаю текущую версию уродливой по моему стандарту.

xdtTransform 16.04.2019 12:03
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
2
8
195
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Это даст вам желаемый результат.

;with family as
(
    select 1 FamilyID, 'Foo' Family union select 2, 'Bar' union select 3, 'ABC'
), child as
(
    select 1 ChildID, 1 FamilyID ,'John' ChildName union
    select 2, 1, 'Joe' union
    select 3, 2, 'Jane' union
    select 4, 2, 'Jessica' union
    select 5, 3, 'XXX'union
    select 6, 3, 'YYY'
), pets as 
(
    select 1 petid , 2 childid, 'FooBar' pet  union
    select 2, 5, 'Huey' union
    select 3, 6, 'Dewey'  
)

SELECT T.FamilyID, Max(Family) Family, MIN(CNT) [Min] , MAX(CNT) [Max]  FROM 
(
    SELECT f.FamilyID, C.ChildID, SUM(case when petid is null then 0 else 1 end) CNT  FROM Family F 
    JOIN Child C ON F.FamilyID = C.FamilyID 
    LEFT JOIN Pets P ON C.ChildID = P.ChildID
    GROUP BY F.FamilyID, C.ChildID 
    ) T JOIN Family F on T.FamilyID = F.FamilyID GROUP BY T.FamilyID 
HAVING MIN(CNT) = 0 AND  MAX(CNT) > 0

Спасибо, собирался прокомментировать, что счетчик возвращает единицу при нулевом значении, но вы его отредактировали. 2 groupy by - это решение, которое я пытался получить от внутреннего запроса. Большое спасибо за ваше время.

xdtTransform 08.04.2019 16:06

если решение сработало для вас @xdtTransform, примите его как ответ.

Taimur Khan 08.04.2019 16:09

Всегда просматривайте все мои действия StackOverflow в конце недели. Я обычно принимаю ответ в этот момент.

xdtTransform 08.04.2019 16:23

похоже, вы близки, но если я правильно понимаю:

With parent as (
select 'Charlie' name from dual union all
select 'Ben' name from dual union all
select 'Bob' name from dual union all
select 'Harry' name from dual 
)
,child as (
select 'Ben' parentname, 'Bebbie' name from dual union all
select 'Ben' parentname, 'Tilda' name from dual union all
select 'Bob' parentname, 'Shara' name from dual union all
select 'Bob' parentname, 'Sandra' name from dual 
)
,pet as (
select 'Tilda' childname, 'Dog' pet from dual union all
select 'Tilda' childname, 'Cat' pet from dual union all
select 'Shara' childname, 'Bird' pet from dual union all
select 'Shara' childname, 'Snake' pet from dual 
)
select pa.name,ch.name,count(pe.pet)
from parent pa
inner join child ch on ch.parentname = pa.name
left join pet pe on pe.childname = ch.name
group by pa.name,ch.name

Запрос

 select  family.ID, family.name 
 from      family 
 left join child on family.ID = child.family_id
 left join pet on pet.child_ID = child.Id
 group by  family.name,family.ID
 having  count(child.id) > 1 and  count( pet.id) <>0 and count(child.id) > count( pet.id) 

Выход

Привет, пожалуйста, объясните свой ответ, почему это будет решением проблемы OP. Это поможет ОП и будущим посетителям сайта. Спасибо!

d_kennetz 08.04.2019 16:50

Привет, я изменил запрос в соответствии с последней информацией, представленной в описании вопроса. Надеюсь это поможет.

ch2019 08.04.2019 17:33

Да, просто и работает. почему-то пропустил count(child.id) > count( pet.id).

xdtTransform 15.04.2019 14:18

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