postgresql 如何按a,b分组并返回N行b的集合

6yjfywim  于 2023-06-29  发布在  PostgreSQL
关注(0)|答案(2)|浏览(130)

使用Postgres 9.3.2,我希望得到req_status的计数,并按req_timecustomer_id分组,并为每个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

我如何才能做到这一点?

5kgi1eie

5kgi1eie1#

要查看结果中缺少的行,请将LEFT JOIN添加到可能行的完整网格。网格由(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(空值不计数)。
假设req_timedate(不是timestamp)。
相似:

  • array_agg group by和null
4uqofj5v

4uqofj5v2#

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

相关问题