【问题标题】:How to group by a, b and return set of N rows of b如何按a,b分组并返回b的N行集
【发布时间】:2014-03-21 18:46:17
【问题描述】:

使用 Postgres 9.3.2,我想获得由 req_timecustomer_id 分组的 req_status 的计数,并为每个 customer_id 返回一组 n 行,即使在req_status 计数为零。

req_time     req_id   customer_id     req_status
----------------------------------------------- 
2014-03-19    100        1            'FAILED'
2014-03-19    102        1            'FAILED'
2014-03-19    105        1            'OK'
2014-03-19    106        2            'FAILED'
2014-03-20    107        1            'OK'
2014-03-20    108        2            'FAILED'
2014-03-20    109        2            'OK'
2014-03-20    110        1            'OK'

输出

req_time  customer_id   req_status  count
-------------------------------------------
2014-03-19    1            'FAILED'   2
2014-03-19    1            'OK'       1
2014-03-19    2            'FAILED'   1
2014-03-19    2            'OK'       0
2014-03-20    1            'FAILED'   0
2014-03-20    1            'OK'       2
2014-03-20    2            'FAILED'   1
2014-03-20    2            'OK'       1

我怎样才能做到这一点?

【问题讨论】:

    标签: sql postgresql left-join aggregate-functions postgresql-9.1


    【解决方案1】:

    要在结果中也看到缺失的行,左连接到可能行的完整网格。网格是由 (req_time, customer_id, req_status) 与交叉连接的所有可能组合构建的:

    SELECT d.req_time, c.customer_id, s.req_status, count(t.req_time) AS ct
    FROM  (
       SELECT generate_series (min(req_time), max(req_time), '1 day')::date
       FROM   tbl
       ) d(req_time)
    CROSS  JOIN (SELECT DISTINCT customer_id FROM tbl)  c(customer_id)
    CROSS  JOIN (VALUES ('FAILED'::text), ('OK'))       s(req_status)
    LEFT   JOIN  tbl t USING (req_time, customer_id, req_status)
    GROUP  BY 1,2,3
    ORDER  BY 1,2,3;
    

    对实际表中的一列进行计数,如果未找到匹配项,则为 0(NULL 值不计)。

    假设req_timedate(不是timestamp)。

    类似的答案在这里:
    array_agg group by and null

    【讨论】:

    • 谢谢欧文。您的查询将排除 count=0 的行。再看看我想要的输出。
    • @McKibet:我明白了。更新了我的答案。
    【解决方案2】:

    SQL Fiddle

    select
        s.req_time, s.customer_id,
        s.req_status,
        count(t.req_status is not null or null) as "count"
    from
        t
        right join (
            (
                select distinct customer_id, req_time
                from t
            ) q
            cross join
            (values ('FAILED'), ('OK')) s(req_status)
        ) s on
            t.req_status = s.req_status and
            t.customer_id = s.customer_id and
            t.req_time = s.req_time
    group by 1, 2, 3
    order by 1, 2, 3
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多