10

这与this question密切相关,但增加了另一个要求。

给定一个父表'parent'

╔════════════╦════════╗
║ PARENT_ID  ║ NAME   ║
╠════════════╬════════╣
║         1  ║ bob    ║
║         2  ║ carol  ║
║         3  ║ stew   ║
╚════════════╩════════╝

以及父级和(此处未指定)属性表之间的多对多关系表“rel”

╔════════════╦══════════╗
║ PARENT_ID  ║ PROP_ID  ║
╠════════════╬══════════╣
║         1  ║       5  ║
║         1  ║       1  ║
║         2  ║       5  ║
║         2  ║       4  ║
║         2  ║       1  ║
║         3  ║       1  ║
║         3  ║       3  ║
╚════════════╩══════════╝

如何选择具有所有具有一组指定关系的所有父母?例如,使用样本数据,我如何找到与属性 5 和 1 有关系的所有父母?

4

10 回答 10

13
SELECT PARENT_ID
FROM rel
GROUP BY PARENT_ID
HAVING SUM(PROP_ID NOT IN (5,1)) = 0
   AND SUM(PROP_ID = 1) = 1 
   AND SUM(PROP_ID = 5) = 1
于 2013-01-01T19:00:37.657 回答
4

这种替代方案具有恒定语句结构和只有一个参数的好处,与您正在寻找的关系数量无关:

SELECT parent_id FROM rel 
GROUP BY parent_id 
HAVING GROUP_CONCAT(prop_id ORDER BY prop_id ASC SEPARATOR ",") = '1,5';

缺点:

  • 您需要预先准备一个有序的、逗号分隔的 prop_ids 字符串。
  • 这适用于 MySQL,但不适用于所有数据库服务器。
于 2015-10-28T19:40:04.390 回答
3

如果要选择至少为 5 和 1 的所有父母,可以使用:

SELECT PARENT_ID
FROM rel
GROUP BY PARENT_ID
HAVING SUM(PROP_ID = 1)
       AND SUM(PROP_ID = 5)
       AND SUM(PROP_ID NOT IN (5,1)) = 0

如果您恰好需要一个 5 和一个 1,请参阅答案

于 2013-01-01T19:09:28.857 回答
2

有两个嵌套的子查询,像这样..

 Select pa.Id
 From parents pa
 Where not exists -- This ensures that all specifies properties exist
    (Select * From property y
     Where propertyId In (1,5)
         And Not Exists
             (Select * From parentProperty
              Where parentId = pa.parentId 
                  And propertyId = y.propertyId ))
   And not exists -- This ensures that only specified list of properties exist
    (Select * From parentProperty
     Where parentId = pa.parentId 
        And propertyId Not In (1,5) )

第一个内容为“显示指定属性列表中没有属性且不在指定父级的父级属性表中的所有父级......”

第二个子查询显示:“还要确保在 parentProperties 表中不存在任何不在指定列表中的属性的父属性的记录。”

于 2013-01-01T19:08:50.487 回答
2
SELECT PARENT_ID
FROM rel
GROUP BY PARENT_ID
HAVING
  COUNT(PROP_ID)=2 AND
  COUNT(DISTINCT case when PROP_ID IN ( 1, 5 ) then PROP_ID end)=2

这将选择所有PARENT_ID恰好有两行的所有行,并且恰好有两个不重复PROP_ID的匹配。

于 2013-01-01T19:48:17.490 回答
1

假设 (PARENT_ID, PROP_ID) 是唯一的:

SELECT r1.PARENT_ID
FROM rel r1
INNER JOIN rel r2 ON r1.PARENT_ID = r2.PARENT_ID AND r2.PROP_ID = 5 
INNER JOIN rel r3 ON r1.PARENT_ID = r3.PARENT_ID AND r3.PROP_ID = 1
GROUP BY r1.PARENT_ID
HAVING COUNT(*) = 2

或者,

SELECT parent.PARENT_ID
FROM parent
INNER JOIN
(
    SELECT PARENT_ID
    FROM rel
    WHERE PROP_ID IN (1,5)
    GROUP BY PARENT_ID
    HAVING COUNT(*) = 2
) good ON parent.PARENT_ID = good.PARENT_ID
LEFT OUTER JOIN rel bad ON parent.PARENT_ID = bad.PARENT_ID 
    AND bad.PROP_ID NOT IN (1,5)
WHERE bad.PARENT_ID IS NULL

甚至,

SELECT DISTINCT parent.PARENT_ID
FROM parent
INNER JOIN rel r2 ON parent.PARENT_ID = r2.PARENT_ID AND r2.PROP_ID = 5 
INNER JOIN rel r3 ON parent.PARENT_ID = r3.PARENT_ID AND r3.PROP_ID = 1
LEFT OUTER JOIN rel r0 ON parent.PARENT_ID = r0.PARENT_ID 
    AND r0.PROP_ID NOT IN (1,5)
WHERE r0.PARENT_ID IS NULL
于 2013-01-01T18:58:18.857 回答
0

如果 MySql 支持minus,查询可能如下所示:

select parent_id
from rel
where prop_id in (5,1)
group by parent_id
having count(distinct prop_id)=2 and count(prop_id)=2
minus
select parent_id
from rel
where prop_id not in (5,1);

not in删除那些超过 (5,1) 的关系,例如 (5,1,3)。

我知道您正在使用 MySql,因此我的回答是错误的。只是把它当作另一个想法。

于 2013-01-01T20:57:53.723 回答
0

即使 (PARENT_ID, PROP_ID) 不是唯一的,此查询也是正确的:

SELECT PARENT_ID FROM rel WHERE
PROP_ID IN (5,1) AND 
PARENT_ID NOT IN (SELECT DISTINCT PARENT_ID FROM rel WHERE PROP_ID NOT IN (5,1))
GROUP BY PARENT_ID HAVING COUNT(DISTINCT PROP_ID) = 2
于 2013-03-03T06:15:25.850 回答
-1

希望对你有帮助:

SELECT p.PARENT_ID , r.PROP_ID FROM rel r LEFT JOIN parent p ON p.PARENT_ID = r.PARENT_ID WHERE r.PROP_ID = 5 OR r.PROP_ID = 1
于 2013-01-01T19:14:01.457 回答
-3

您可以通过 group by 执行此操作。

SELECT PARENT_ID FROM link_tbl WHERE PROP_ID IN (5,1) GROUP BY PARENT_ID HAVING COUNT(*) = 2

于 2013-01-01T18:59:43.613 回答