Считать по критериям по разделу - PullRequest
0 голосов
/ 18 декабря 2018

У меня есть эта таблица в базе данных 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;

У меня есть этот запрос:

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;

Я хотел бы иметь ТОТ-СЧЕТ для PARTITION COLA / COLBвариации <10.Я попытался добавить количество в выражении case: </p>

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)

Но я получил эту ошибку обратно:

42803: вызовы агрегатных функций не могут содержать вызовы оконных функций.

###### ИЗМЕНЕНО после СОВЕТА "The Impaler"
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

1 Ответ

0 голосов
/ 18 декабря 2018

Это не ответ, а комментарий, который не помещается в разделе комментариев.Когда у вас есть несколько оконных функций, и вы хотите управлять их результатами (как в этом случае), я склонен вычислять их в CTE (Common Table Expression);затем я использую их как простые скалярные значения в основном запросе.Это делает мою жизнь намного проще.

Например, такой запрос:

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

Я бы перефразировал запрос: а) предварительно вычислить «сложные» значения, а затем 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

Возможно, вы можете использовать эту стратегию, чтобы ваш запрос выглядел проще, поэтому отладка будет проще.

...