SQL - 孩子必须包含所有指定的值(SQL - child must contain all s

2019-10-20 03:55发布

我有以下数据的两个表:

Test_parent

parent_id   title
------------------
1   Parent1
2   Parent2
3   Parent3
4   Parent4

Test_child

child_id    parent_id   property
------------------------------------
1   1   A
2   2   A
3   2   B
4   3   A
5   3   C
6   4   A

我想选择表test_parent所有行父包含儿童(两者)特性A和B(所以这将是创纪录的PARENT_ID = 2)

这是我写到目前为止最好的解决办法:

select * 
from test_parent p
where (select COUNT(property) 
       from test_child c 
       where p.parent_id = c.parent_id and c.property in ('A', 'B')) = 2

有没有更“正确”的方式?

非常感谢!

这是对象的完全脚本:

CREATE TABLE [dbo].[test_parent](
    [parent_id] [int] IDENTITY(1,1) NOT NULL,
    [title] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_test_parent] PRIMARY KEY CLUSTERED 
([parent_id]))
GO

CREATE TABLE [dbo].[test_child](
    [child_id] [int] IDENTITY(1,1) NOT NULL,
    [parent_id] [int] NOT NULL,
    [property] [nvarchar](10) NOT NULL,
 CONSTRAINT [PK_test_child] PRIMARY KEY CLUSTERED 
([child_id]))
GO

ALTER TABLE [dbo].[test_child]  WITH CHECK ADD  CONSTRAINT [FK_test_child_test_child] FOREIGN KEY([parent_id])
REFERENCES [dbo].[test_parent] ([parent_id])
GO

ALTER TABLE [dbo].[test_child] CHECK CONSTRAINT [FK_test_child_test_child]
GO

SET IDENTITY_INSERT [dbo].[test_parent] ON;
INSERT INTO [dbo].[test_parent]([parent_id], [title])
SELECT 1, N'Parent1' UNION ALL
SELECT 2, N'Parent2' UNION ALL
SELECT 3, N'Parent3' UNION ALL
SELECT 4, N'Parent4'

SET IDENTITY_INSERT [dbo].[test_parent] OFF;
GO

SET IDENTITY_INSERT [dbo].[test_child] ON;

INSERT INTO [dbo].[test_child]([child_id], [parent_id], [property])
SELECT 1, 1, N'A' UNION ALL
SELECT 2, 2, N'A' UNION ALL
SELECT 3, 2, N'B' UNION ALL
SELECT 4, 3, N'A' UNION ALL
SELECT 5, 3, N'C' UNION ALL
SELECT 6, 4, N'A'
GO

SET IDENTITY_INSERT [dbo].[test_child] OFF;

Answer 1:

我不知道“更正确”,但一个简单的使用JOIN GROUP BY / HAVING会做没有一个子查询;

SELECT test_parent.parent_id, test_parent.title 
FROM test_parent
JOIN test_child ON test_child.parent_id=test_parent.parent_id
 AND test_child.property IN ('A','B')
GROUP BY test_parent.parent_id, test_parent.title
HAVING COUNT(DISTINCT test_child.property)=2

一个SQLfiddle测试用 。

这将基本上加入母体与具有由父行等于“A”或“B”,基团的性质的任何儿童和计数的不同值property对孩子。 如果它是等于2(“A”和“B”是两个可能的值),则返回父。



Answer 2:

在这个问题查询

select * 
from   test_parent p
where  2 = (select COUNT(property) 
            from test_child c 
            where p.parent_id = c.parent_id 
              and c.property in ('A', 'B'))

有一个小问题:如果有两个孩子,都与“A”或两者与“B”的家长会在结果显示,一这是从不同的要求说明。 它也不会超过两个子显示父,即使他们只有“A”和“B”的属性,例如,如果我们添加的行

child_id | parent_id | property
       7 |         5 |        A
       8 |         5 |        B
       9 |         5 |        A

到母体5不会在结果test_child的数据(表示,图5是在父表)

写约阿希姆伊萨克森的查询另一种方式是对孩子性移动支票给HAVING子句

SELECT tp.id, tp.title
FROM   test_parent tp
       INNER JOIN test_child tc ON tp.parent_id = tc.parent_id
GROUP BY tp.id, tp.title
HAVING COUNT(DISTINCT tp.property) = 2
   AND SUM(CASE WHEN tp.property IN ('A', 'B') THEN 0 ELSE 1 END) = 0


Answer 3:

你可以试试这个。 我相信它会表现得更好,但你shoukd检查excecution计划进行检查。

 SELECT distinct tp.title
    FROM test_parent tp
    INNER JOIN test_child ca on tp.parent_id=ca.parent_id and ca.property='A'
    INNER JOIN test_child cb on ca.parent_id=cb.parent_id and cb.property='B'


文章来源: SQL - child must contain all specified values