Выберите Parent с нулевым, а не нулевым дочерним элементом - PullRequest
0 голосов
/ 08 апреля 2019

Учитывая 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. Мне нужна семья, где у некоторых детей есть домашние животные, а у некоторых нет.

Семья: Id, Имя

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

Ребенок: Id, Family_Id, Name

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

Pet: Id, Child_Id, Name

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

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

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


Создание таблицы:
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');

Ответы [ 3 ]

3 голосов
/ 08 апреля 2019

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

;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
1 голос
/ 08 апреля 2019

Запрос

 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) 

Вывод

enter image description here

0 голосов
/ 08 апреля 2019

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

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...