SQL检索包含其他表

时间:2016-08-29 01:06:50

标签: sql postgresql relational-division

我在一个特定场景中面临一些使用SQL检索数据的问题:

假设我有以下表格:

  • A(id,attr_a,attr_b);
  • B(id,attr_d,attr_e);
  • C(id_a,id_b);

正如您所看到的,表CFK引用表A中的ID,并引用表C中的ID。

我需要检索每个A行与每个A行相关的表B行。

在现实生活场景中,假设A表示用户,B表示权限,C是多个与用户权限相关联的实体,我只希望得到拥有所有权限的用户

5 个答案:

答案 0 :(得分:2)

select A.*
from A
join C on id_a = id
group by id
having count(id) = (select count(*) from B)

不需要使用子查询,因为A.id是主键(或至少是唯一的)作为C.id_a引用的列。

答案 1 :(得分:1)

以下查询应返回所有A条记录,对于给定的ID,它们与B表中的每条记录匹配。请注意,如果要返回A中的每个完整记录,则必须使用子查询。

SELECT t1.*
FROM A t1
INNER JOIN
(
    SELECT A.id
    FROM A
    INNER JOIN C
        ON A.id = C.id_a
    GROUP BY A.id
    HAVING COUNT(*) = (SELECT COUNT(*) FROM B)
) t2
    ON t1.id = t2.id

答案 2 :(得分:1)

假设FK约束强制执行参照完整性,所有关键列NOT NULL以及(id_a, id_b)C上的UNIQUE或PK约束。

如果您只需要ID,则只能使用表C。不要浪费时间加入A

SELECT id_a
FROM   C
GROUP  BY 1
HAVING count(*) = (SELECT count(*) FROM B);

如果您需要A中的列或整行,请在聚合并删除不符合条件的行后加入 。应该是最快的。

SELECT A.*
FROM  (
   SELECT id_a AS id
   FROM   C
   GROUP  BY 1
   HAVING count(*) = (SELECT count(*) FROM B)
   ) c
JOIN   A USING (id);

答案 3 :(得分:0)

看起来你真的只需要表C,如果你想要的是拥有所有权限的用户列表。一种方法是使用CONCAT查看C.id_aC.id_b之间的配对作为一个字符串:

SELECT C.id_a
 FROM C
 GROUP BY C.id_a
 HAVING COUNT(DISTINCT CONCAT(C.id_a, C.id_b)) =
 (SELECT COUNT(DISTINCT C.id_b)
  FROM C)

在这里测试:http://sqlfiddle.com/#!9/f92a54/3

答案 4 :(得分:0)

您不需要计算,您只需要检查(非)存在的行:

SELECT *
FROM A
WHERE NOT EXISTS (
        SELECT * FROM B
        WHERE NOT EXISTS (
                SELECT * FROM C
                WHERE C.id_a = A.id AND C.id_b = B.id
                )
        );