SQL:按条件求和

SQL:按条件求和,sql,oracle,sum,criteria,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 -

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


谢谢

您可以使用
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


戈登·林诺夫的答案很好。
下面这是一个不同的口味(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

您确定按id排序的
desc
desc
吗?@BarbarosÖzhan。对请参阅答案的编辑。谢谢!我正试着根据我的环境来调整这一点,这似乎很好。还有一件事:我怎样才能把“PROD”项目的年份作为“grp”项目的内容呢?非常好的解决方案,恭喜你,我添加了一个带有
demo
@user343081的orderby子句。我不知道你的评论是什么意思。在这个问题中没有“grp”项——它被添加在这个答案中——根据这个问题,“年”和分组之间没有关系。也许您应该问另一个关于示例数据和所需结果的问题。如果在最后一个prod行之后有一个或多个非prod类型的行,该怎么办?e、 g.
9 02/12/2018测试80
10 03/12/2018测试90
。这些行的和值应该是170,还是应该为null?好问题:)。这些行应该求和。@Boneist:您关于非“prod”值的处理方式的问题很好!我一直在与不一致的数据作斗争,刚刚发现我在数据中发现了这种情况。因此,现在的问题是,即使不存在“prod”值,如何将当前年份的数据分组,然后按prod值分组?我建议您将此作为一个新问题提出,使用示例输入数据显示您需要帮助的场景,以及您想要获得的输出。