Средняя сумма по условию - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть эта таблица и образец данных в базе данных Postgres

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,
CASE
  WHEN (datum >= now() - interval '6 month') THEN SUM(COLD)/6
  ELSE '0'
END AS datum_range
FROM testAAA
group by COLA,COLB,COLC;

Моя цель состоит в том, чтобысгенерировать среднее значение за 6 месяцев для столбца COLD, используя в качестве комбинации COLA + COLB + COLC, если условие интервала DATE выполнено, пропуская нулевое значение.

Прямо сейчас я получаю эту ошибку:

Error(s), warning(s):

42803: column "testaaa.datum" must appear in the GROUP BY clause or be used in an aggregate function

Как исправить вышеуказанную ошибку?

Ответы [ 2 ]

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

demo: db <> fiddle

SELECT *,
    SUM(COLD) FILTER (WHERE datum >= now() - interval '6 month') OVER (PARTITION BY COLA, COLB, COLC) / 6.0 as avg
FROM testAAA

Результат:

| id |      datum |   cola |    colb | colc | cold |                avg |
|----|------------|--------|---------|------|------|--------------------|
|  1 | 2018-01-01 | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  2 | 2018-02-01 | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  3 | 2018-03-01 | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  4 |     (null) | PLANTA | VENDORA |  OPA |    1 |  4.166666666666667 |
|  5 | 2018-10-01 | PLANTA | VENDORA |  OPA |    5 |  4.166666666666667 |
|  6 | 2018-10-01 | PLANTA | VENDORA |  OPA |   10 |  4.166666666666667 |
|  8 | 2018-10-01 | PLANTA | VENDORA |  OPA |   10 |  4.166666666666667 |
|  9 | 2018-11-01 | PLANTA | VENDORA |  OPB |    5 | 0.8333333333333334 |
|  7 | 2018-11-01 | PLANTA | VENDORB |  OPA |   50 |  8.333333333333334 |

[demo: db <> fiddle] [4]

  1. Использование оконной функции SUM(...) OVER (PARTITION BY ...) позволяет выполнять агрегирование SUM, как в предложении GROUP, но с сохранением исходных строк.Агрегация добавляется в виде отдельного столбца. Предложение
  2. FILTER позволяет фильтровать входные данные для функций агрегирования.Таким образом, вы можете агрегировать только строки с datum >= ...
0 голосов
/ 17 декабря 2018

Почему бы просто не переместить условие в предложение where:

SELECT   cola, colb, colc, SUM(cold) / 6
FROM     testAAA
WHERE    datum >= NOW() - INTERVAL '6 MONTH' 
GROUP BY cola, colb, colc
...