postgresql 将日期列合并为一列

idv4meu8  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(2)|浏览(152)

数据库中有合同签订日期和合同终止日期的列。我需要按日期分组合同签订数量和合同取消数量。
我写了一些问题

with conn as (select date_signing::date as dt_sign, count(date_signing) as signing from services GROUP by date_signing::date),
disconn as (select date_cancellation::date as dt_canc, count(date_cancellation) as cancelling from services GROUP by date_cancellation::date)
select * from conn full join disconn on conn.dt_sign = disconn.dt_canc

字符串
结果如下:


的数据
但我需要这个结果(例如):

date        signing       cancelling
2019-08-09     1             null
2020-05-05   null              1


我需要一个日期栏和签署和终止栏看到的动态。请告诉我在哪个方向思考。

1szpjjfi

1szpjjfi1#

FULL JOIN看起来很适合这个工作。小建议:

WITH sig AS (
   SELECT date_signing::date AS the_date, count(*) AS signing
   FROM   services
   GROUP  BY 1
   )
, can AS (
   SELECT date_cancellation::date AS the_date, count(*) AS cancelling
   FROM   services
   GROUP  BY 1
   )
SELECT *
FROM   sig
FULL   JOIN can USING (the_date)
WHERE  the_date IS NOT NULL;  -- optional to eliminate row(s) with null date

字符串
为了简化,使用相同的列别名并与USING子句联接以获得单个输出列。
此外,count(*)更快,并且在这方面是等效的(除了还获得the_date IS NULL的正确计数)。
相关:

  • 我从查询中获得了不同的结果,例如:“e.id”或"e.id“
zlhcx6iw

zlhcx6iw2#

如果您不想在此报表中出现空白,特别是如果您想放大某个期间,请生成一个日历并对其进行left join计算。基于此计算也会生成一个适当的零,而不是null.Demo at db<>fiddle

select d::date,count(*)filter(where d::date=s.date_signing::date)signing,
               count(*)filter(where d::date=s.date_cancellation::date)cancelling 
from generate_series('2023-02-22'::timestamp,'2023-03-11','1 day')_(d)
left join services s on d::date in(s.date_signing::date,s.date_cancellation::date)
group by 1 order by 1;

字符串
如果你喜欢你现在的布局,你根本不需要join。读出日期和sum()

select the_date, sum(s)signing, sum(c)cancelling
from (select  date_cancellation::date AS the_date,0 AS s,1 AS c from services
      union all select date_signing::date,1,0 from services)_
group by 1 order by 1;


或具有类似的预聚合/子聚合:

select the_date, sum(s)signing, sum(c)cancelling from (
  select date_cancellation::date the_date,0 s,count(*)c from services group by 1
  union all select date_signing::date,count(*),0 from services group by 1)_
group by 1 order by 1;


Performance&plans
unnest()转换为聚合体:

select the_date,sum(s)signing,sum(c)cancelling 
from services, 
unnest(array[ (date_cancellation::date, 0    ,1    )
             ,(date_signing::date     , 1    ,0    ) ] )
             _(the_date date          , s int,c int)
group by 1 order by 1;
select the_date,sum(s::int)signing,sum((not s)::int)cancelling 
from services,
unnest(array[true,false],
       array[date_signing,date_cancellation]::date[])_(s,the_date)
group by 1 order by 1;
select the_date,count(*)filter(where o='signing'   )signing
               ,count(*)filter(where o='cancelling')cancelling
from services,
unnest(array['signing'   ,'cancelling'],
       array[date_signing,date_cancellation]::date[])_(o,the_date)
group by 1 order by 1;
select the_date::date
      ,sum( extract(h from the_date))signing
      ,sum((extract(h from the_date) =0)::int)cancelling 
from services,
unnest(array[date_signing::date+interval'1h',date_cancellation::date])_(the_date)
group by 1 order by 1;

相关问题