sql合并两个子查询
Posted
技术标签:
【中文标题】sql合并两个子查询【英文标题】:sql combine two subqueries 【发布时间】:2010-06-11 21:08:26 【问题描述】:我有两张桌子。表 A
有一个 id
列。表B
有一个Aid
列和一个type
列。示例数据:
A: id
--
1
2
B: Aid | type
----+-----
1 | 1
1 | 1
1 | 3
1 | 1
1 | 4
1 | 5
1 | 4
2 | 2
2 | 4
2 | 3
我想从表 A 中获取所有 ID,其中有一定数量的类型 1 和类型 3 操作。我的查询如下所示:
SELECT id
FROM A
WHERE (SELECT COUNT(type)
FROM B
WHERE B.Aid = A.id
AND B.type = 1) = 3
AND (SELECT COUNT(type)
FROM B
WHERE B.Aid = A.id
AND B.type = 3) = 1
以上面的数据为例,应该只返回 id 1
。
我可以以某种方式组合这 2 个子查询吗?目标是使查询运行得更快。
【问题讨论】:
【参考方案1】:postgres 是否支持 CTE?
WITH counts (Counts, Type, Aid) as (
select count(type), type
from b group by Type, Aid
)
select id
from A
join Counts B1 on b1.Aid = a.id and b1.type = 1
join Counts B3 on b3.Aid = a.id and b3.type = 3
where
b1.counts = 3 and b3.counts = 1
我建议比较执行计划,但我怀疑它会相似,因为一切都应该在执行前折叠。
【讨论】:
是的,Postgres 从 v8.4 开始支持 WITH 子句,包括递归:postgresql.org/docs/current/static/sql-select.html【参考方案2】:Select ...
From A
Join (
Select B.Id
, Sum ( Case When B.Type = 1 Then 1 Else 0 End ) As Type1Count
, Sum ( Case When B.Type = 3 Then 1 Else 0 End ) As Type3Count
From B
Where B.Type In(1,3)
Group By B.Id
) As Z
On Z.Id = A.Id
Where Z.Type1Count = 3
And Z.Type3Count = 1
【讨论】:
【参考方案3】:这在 TSQL 中有效,在 Postgres 中有效吗?
SELECT A.ID
FROM A
WHERE A.ID in
(
SELECT AID
FROM B
GROUP BY AID
HAVING
SUM(CASE WHEN Type = 1 THEN 1 ELSE 0 END) = 3
OR SUM(CASE WHEN Type = 3 THEN 1 ELSE 0 END) = 1
)
【讨论】:
【参考方案4】:另一种选择:
SELECT DISTINCT Aid FROM (
SELECT Aid,type,count(*) as n from B
GROUP BY Aid,type, ) as g
WHERE ( g.n=1 AND g.type = 3 )
OR ( g.n=3 AND g.type = 1 )
不过,我怀疑这会比你原来的表现更好。 你似乎在做最好的策略:只计算候选行。 也许一些冗余的预过滤可能会有所帮助:
SELECT DISTINCT Aid FROM (
SELECT Aid,type,count(*) as n from B
WHERE g.type = 3 OR g.type = 1 -- prefilter
GROUP BY Aid,type, ) as g
WHERE ( g.n=1 AND g.type = 3 )
OR ( g.n=3 AND g.type = 1 )
【讨论】:
以上是关于sql合并两个子查询的主要内容,如果未能解决你的问题,请参考以下文章