我在一个特定场景中面临一些使用SQL检索数据的问题:
假设我有以下表格:
A
(id,attr_a,attr_b); B
(id,attr_d,attr_e); C
(id_a,id_b); 正如您所看到的,表C
有FK
引用表A
中的ID,并引用表C
中的ID。
我需要检索每个A
行与每个A
行相关的表B
行。
在现实生活场景中,假设A
表示用户,B
表示权限,C
是多个与用户权限相关联的实体,我只希望得到拥有所有权限的用户
答案 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_a
和C.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)
答案 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
)
);