SQL: сумма по критериям - PullRequest
       11

SQL: сумма по критериям

0 голосов
/ 17 октября 2018

Я работаю с Oracle и не могу выполнить запрос, который мне нужен на данный момент.

Предположим, у меня есть следующая таблица:

- ID    Date    Type    Value
 - 1    01/12/2016  prod    1
 - 2    01/01/2017  test    10
 - 3    01/06/2017  test    20
 - 4    01/12/2017  prod    30
 - 5    15/12/2017  test    40
 - 6    01/01/2018  test    50
 - 7    01/06/2018  test    60
 - 8    01/12/2018  prod    70

Мне нужно сложить ЗНАЧЕНИЯ междуТИПЫ "prod" + последнее ЗНАЧЕНИЕ "prod".Результаты должны быть:

- 1 01/01/2016 - 1
- 2 01/01/2017 - 60
- 3 01/06/2017 - 60
- 4 01/12/2017 - 60
- 5 15/12/2017 - 220
- 6 01/01/2018 - 220
- 7 01/06/2018 - 220
- 8 01/12/2018 - 220

Сначала я должен был суммировать ЗНАЧЕНИЯ к ГОДУ без учета ТИПОВ.Потребность изменилась, и я не вижу, как начать определять для каждой строки, которая является предыдущей датой «prod», и суммировать каждое ЗНАЧЕНИЕ, включая последний ТИП «prod».

Спасибо

Ответы [ 2 ]

0 голосов
/ 17 октября 2018

Ответ Гордона Линоффа великолепен.
Это ниже просто для другого вкуса (12c +)

Настройка:

ALTER SESSION SET NLS_DATE_FORMAT  = 'DD/MM/YYYY';
CREATE TABLE TEST_TABLE(
  THE_ID INTEGER,
  THE_DATE DATE,
  THE_TYPE CHAR(4),
  THE_VALUE INTEGER);

INSERT INTO TEST_TABLE VALUES (1,TO_DATE('01/12/2016'),'prod',1);
INSERT INTO TEST_TABLE VALUES (2,TO_DATE('01/01/2017'),'test',10);
INSERT INTO TEST_TABLE VALUES (3,TO_DATE('01/06/2017'),'test',20);
INSERT INTO TEST_TABLE VALUES (4,TO_DATE('01/12/2017'),'prod',30);
INSERT INTO TEST_TABLE VALUES (5,TO_DATE('15/12/2017'),'test',40);
INSERT INTO TEST_TABLE VALUES (6,TO_DATE('01/01/2018'),'test',50);
INSERT INTO TEST_TABLE VALUES (7,TO_DATE('01/06/2018'),'test',70);
INSERT INTO TEST_TABLE VALUES (8,TO_DATE('01/12/2018'),'prod',60);
COMMIT;

Запрос:

SELECT
THE_ID, THE_DATE, MAX(RUNNING_GROUP_SUM) OVER (PARTITION BY THE_MATCH_NUMBER) AS GROUP_SUM
FROM TEST_TABLE
MATCH_RECOGNIZE (
  ORDER BY THE_ID
  MEASURES
    MATCH_NUMBER() AS THE_MATCH_NUMBER,
    RUNNING SUM(THE_VALUE) AS RUNNING_GROUP_SUM
  ALL ROWS PER MATCH
  AFTER MATCH SKIP PAST LAST ROW
  PATTERN (TEST_TARGET{0,} PROD_TARGET)
  DEFINE TEST_TARGET AS THE_TYPE = 'test',
    PROD_TARGET AS THE_TYPE = 'prod')
ORDER BY THE_ID ASC;

Результат:

    THE_ID THE_DATE    GROUP_SUM
---------- ---------- ----------
     1 01/12/2016          1
     2 01/01/2017         60
     3 01/06/2017         60
     4 01/12/2017         60
     5 15/12/2017        220
     6 01/01/2018        220
     7 01/06/2018        220
     8 01/12/2018        220
0 голосов
/ 17 октября 2018

Вы можете определить группы с помощью совокупной суммы на type = 'PROD' - в обратном порядке, а затем использовать оконную функцию для окончательного суммирования:

select t.*,
       sum(value) over (partition by grp) as total
from (select t.*,
             sum(case when type = 'PROD' then 1 else 0 end) over (order by id desc) as grp
      from t
     ) t
 order by id;

Чтобы увидеть логику группировки, посмотрите на:

ID    Date    Type    Value      Grp
1    01/12/2016  prod    1        3
2    01/01/2017  test    10       2
3    01/06/2017  test    20       2
4    01/12/2017  prod    30       2
5    15/12/2017  test    40       1
6    01/01/2018  test    50       1
7    01/06/2018  test    60       1
8    01/12/2018  prod    70       1

Определяет группы, которые необходимо суммировать.DESC потому что "prod" оканчивает группу.Если бы «prod» начал группу (то есть был включен в сумму в следующей строке), тогда будет использоваться ASC.

Rextester Demo

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...