SQL:按条件求和

时间:2018-10-17 15:14:18

标签: sql oracle sum criteria

我正在与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

我需要对“产品”类型+最后一个“产品”值之间的值求和。 结果应该是:

- 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

我首先必须按年份对VALUES进行求和,而不考虑TYPES。 需求发生了变化,我看不到如何开始识别每一行的前一个“ prod”日期和每个值的总和,包括最后一个“ prod”类型。

谢谢

2 个答案:

答案 0 :(得分:5)

您可以使用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”启动了一个组(即在下一行的总和中包括了该组),则将使用ASC

Rextester Demo

答案 1 :(得分:0)

Gordon Linoff的答案很好。
下面只是一些不同的口味(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