简体   繁体   English

按条件对分区进行计数

[英]Count by criteria over partition

I have this table on a PostGre DB: 我在PostGre数据库上有此表:

CREATE TABLE testAAA(Id integer PRIMARY KEY, datum date, COLA text, COLB text, COLC text, COLD int);

/* Create few records in this table */
INSERT INTO testAAA VALUES(1,to_date('01/01/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(2,to_date('01/02/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(3,to_date('01/03/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(4,null,'PLANTA','VENDORA','OPA','1');
INSERT INTO testAAA VALUES(5,to_date('01/10/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','5');
INSERT INTO testAAA VALUES(6,to_date('01/10/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','10');
INSERT INTO testAAA VALUES(7,to_date('01/11/2018','dd/mm/yyyy'),'PLANTA','VENDORB','OPA','50');
INSERT INTO testAAA VALUES(8,to_date('01/10/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPA','10');
INSERT INTO testAAA VALUES(9,to_date('01/11/2018','dd/mm/yyyy'),'PLANTA','VENDORA','OPB','5');
COMMIT;

I do have this query: 我有这个查询:

SELECT COLA,COLB,COLC,to_char(datum,'YYYY-MM') AS datum_c,
    SUM(COLD) FILTER (WHERE (datum >= now() - interval '6 month') AND (datum <= now())) OVER (PARTITION BY COLA, COLB, COLC) / 6.0 AS AVG_6_month,
    /* TO Aggregate at month level we need to PARTITION IT */
    SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA,to_char(datum,'YYYY-MM')) AS TOT_ORDERED,
    SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA,COLB,to_char(datum,'YYYY-MM')) AS TOT_ORDERED_PLANT,
    (SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0) / (SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA))*100 AS Variation,
    CASE
      WHEN (SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0) / (SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA))*100 >= 10 THEN 'A'
     WHEN (SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0) / (SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA))*100 < 10  THEN 'B'
    END AS var_type
FROM testAAA;

I'd like to have the TOT COUNT for PARTITION COLA/COLB of the Variation <10. 我想让变异<10的分区COLA / COLB的总计数。 I tried to add count in the case statement: 我试图在case语句中添加count:

WHEN (SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0) / (SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA))*100 >= 10 THEN count((SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0) / (SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA))*100)

But I got this error back: 但是我得到了这个错误:

42803: aggregate function calls cannot contain window function calls. 42803:聚合函数调用不能包含窗口函数调用。

######EDITED after "The Impaler" TIP 在“ The Impaler”提示后进行###### EDITED
 with x as ( -- first, compute the window functions select COLA,COLB,COLC,to_char(datum,'YYYY-MM') AS datum_c, SUM(COLD) FILTER (WHERE (datum >= now() - interval '6 month') AND (datum <= now())) OVER (PARTITION BY COLA, COLB, COLC) / 6.0 AS AVG_6_month, /* TO Aggregate at month level we need to PARTITION IT */ SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA,to_char(datum,'YYYY-MM')) AS TOT_ORDERED, SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA,COLB,to_char(datum,'YYYY-MM')) AS TOT_ORDERED_PLANT, (SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0) / (SUM(COLD) FILTER (WHERE datum is not null) OVER (PARTITION BY COLA))*100 AS Variation from testAAA ) select*, COUNT(Variation) FILTER (WHERE Variation < 10) OVER (PARTITION BY COLA, COLB) AS below10, COUNT(Variation) FILTER (WHERE Variation > 10) OVER (PARTITION BY COLA, COLB) AS above10 from x 

This is not an answer, but a comment that would not fit in the comments section. 这不是答案,而是注释部分中不适合的注释。 When you have multiple window functions, and you want to operate their results (as in this case) I tend to compute them in a CTE (Common Table Expression); 当您有多个窗口函数时,并且想要操作它们的结果(在这种情况下),我倾向于在CTE(公用表表达式)中计算它们; then, I use them as simple scalar values in the main query. 然后,我将它们用作主查询中的简单标量值。 That makes my life so much easier. 这使我的生活变得更加轻松。

For example, a query like this: 例如,如下查询:

select 
  sum(a) over(partition by region_id order by created_at) /
  sum(b) over(partition by region_id order by deleted_at) as score
from my_table

I would rephrase the query to a) pre-compute the "complex" values and then 2) use them in a simple query, as in: 我将查询改为:a)预计算“复杂”值,然后2)在简单查询中使用它们,如下所示:

with
x as ( -- first, compute the window functions
  select 
    sum(a) over(partition by region_id order by created_at) as sum_a
    sum(b) over(partition by region_id order by deleted_at) as sum_b
  from my_table
)
select
  sum_a,
  sum_b,
  sum_a / sum_b, -- then use them for any purposes
  sum_a * sum_b
from x

Maybe you can use this strategy to make your query look simpler so debugging it will be easier. 也许您可以使用此策略使查询看起来更简单,因此调试起来会更容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM