2010-06-11 83 views
0

我有两个表。表A有一个id列。表B有一个Aid列和一个type列。示例数据:sql组合了两个子查询

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 

我建议比较执行计划,但我怀疑这将是类似的,因为一切都应该执行之前获得倒塌。

+0

是,Postgres的支持WITH子句,因为V8.4,包括递归:http://www.postgresql.org/docs/current/static/sql- select.html – 2010-06-11 21:27:46

0

这工作在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 
) 
0

另一种选择:

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) 
1
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