SQL查询按两个不同的列分组

时间:2015-02-11 10:48:01

标签: sql postgresql union aggregate-functions

我想要一个查询,其中数据按reseller_id分组parent_res_id = 0。所有其他行应使用parent_res_id而不是reseller_id

例如,parent_res_id 0(管理员帐户)产生了两个reseller_id:1和2.每个人都创建了另一个经销商(分别为3和4)。我想将子行的行与父母一起分组,因此reseller_id 3行添加到1行,reseller_id 4行添加到2.基本上它是深度为1的树。

表:

duration  call_charge reseller_id  parent_res_id
2             1              1           0
3             2              2           0
4             3              3           1
5             4              4           2
6             5              5           1
7             6              6           5

期望的结果:

sum(duration)  sum(call_charege) reseller_id 
19                 15                 1
8                  6                  2

2 个答案:

答案 0 :(得分:2)

使用UNION ALL

SELECT reseller_id, sum(duration) AS sum_dur, sum(call_charge) AS sum_char
FROM  (
   SELECT reseller_id, duration, call_charge
   FROM   tbl
   WHERE  parent_res_id = 0

   UNION ALL
   SELECT parent_res_id, duration, call_charge
   FROM   tbl
   WHERE  parent_res_id <> 0
   ) sub
GROUP  BY 1;

替代CASE表达式:

SELECT CASE WHEN parent_res_id = 0
            THEN reseller_id
            ELSE parent_res_id
       END AS reseller_id
     , sum(duration) AS sum_dur, sum(call_charge) AS sum_char
FROM   tbl
GROUP  BY 1;

结果相同。可能更快,因为它只需要一次表扫描。

对于深度大于1或2的树,递归CTE将是正确的技术。例如:

答案 1 :(得分:0)

它可以与其他样本数据一起使用吗?告诉我。

;WITH CTE
AS (
    SELECT 2 duration
        ,1 call_charge
        ,1 reseller_id
        ,0 parent_res_id

    UNION ALL

    SELECT 3
        ,2
        ,2
        ,0

    UNION ALL

    SELECT 4
        ,3
        ,3
        ,1

    UNION ALL

    SELECT 5
        ,4
        ,4
        ,2
    )
    ,CTE1
AS (
    SELECT reseller_id
        ,duration
        ,call_charge
        ,parent_res_id
    FROM cte
    WHERE parent_res_id = 0

    UNION ALL

    SELECT b.reseller_id
        ,a.duration + b.duration
        ,a.call_charge + b.call_charge
        ,a.parent_res_id
    FROM cte a
    INNER JOIN cte1 b ON a.parent_res_id = b.reseller_id
    WHERE b.parent_res_id = 0
    )
SELECT reseller_id
    ,duration [sum(duration)]
    ,call_charge [sum(call_charege)]
FROM cte1
WHERE parent_res_id > 0
ORDER BY reseller_id