【问题标题】:How to sum a record with its previous not-null ordered by timestamp using ORACLE?如何使用 ORACLE 将记录与其先前按时间戳排序的非空记录相加?
【发布时间】:2018-04-20 22:14:57
【问题描述】:

我有一张像下面这样的表格:

+----+----+-----+--------------+---------+
| C1 | C2 | C3  |   TIMESTMP   | MEASURE |
+----+----+-----+--------------+---------+
| A  | AA | AAA | 201804200000 | 20      |
| A  | AA | AAA | 201804200015 | 2       |
| A  | AA | AAA | 201804200030 | 5       |
| A  | AA | AAA | 201804200045 | null    |
| A  | AA | AAA | 201804200100 | null    |
| A  | AA | AAA | 201804200115 | 12      |
| …  | …  | …   | …            | …       |
| A  | AA | AAA | 201804202345 | 20      |
| B  | BB | BBB | 201804200000 | 8       |
| B  | BB | BBB | 201804200015 | null    |
| B  | BB | BBB | 201804200030 | 1       |
| …  | …  | …   | …            | …       |
+----+----+-----+--------------+---------+

根据这 3 种情况,我必须将 MEASURE 字段中的每个值与其之前的值(通过在 TIMESTMP 字段中取前一刻钟获得)相加:

  1. 如果 MEASURE 中的当前值为 null,则 RESULT 为 null
  2. 如果 MEASURE 中的当前值不为空,并且其在 MEASURE 中的先前值不为空,则将这两个值相加
  3. 如果 MEASURE 中的当前值不为空,并且其在 MEASURE 中的先前值为空,则将 MEASURE 的当前值与其先前的非空值相加。

C1、C2、C3、TIMESTMP字段为key,求和必须在字段c1、c2、c3中具有相同值的记录之间。

结果应该是如下表:

+----+----+-----+--------------+---------+--------------------------------+
| C1 | C2 | C3  |   TIMESTMP   | MEASURE |             RESULT             |
+----+----+-----+--------------+---------+--------------------------------+
| A  | AA | AAA | 201804200000 | 20      | 20                             |
| A  | AA | AAA | 201804200015 | 2       | 22 (2+20)                      |
| A  | AA | AAA | 201804200030 | 5       | 7 (5+2)                        |
| A  | AA | AAA | 201804200045 | null    | null                           |
| A  | AA | AAA | 201804200100 | null    | null                           |
| A  | AA | AAA | 201804200115 | 12      | 17 (12+5)                      |
| …  | …  | …   | …            | …       | …                              |
| A  | AA | AAA | 201804202345 | 20      | X (20+previous value not null) |
| B  | BB | BBB | 201804200000 | 8       | 8                              |
| B  | BB | BBB | 201804200015 | null    | null                           |
| B  | BB | BBB | 201804200030 | 1       | 9 (1+8)                        |
| …  | …  | …   | …            | …       | …                              |
+----+----+-----+--------------+---------+--------------------------------+

【问题讨论】:

    标签: oracle plsql oracle11g


    【解决方案1】:

    我认为最好的选择是创建一个 CTE,然后将其加入您的初始表:

    SQL DEMO

    WITH res (c1, c2, c3, timestamp, measure, result) AS (
        SELECT c1, c2, c3, timestamp, measure
             , measure + COALESCE(LAG(measure) OVER ( PARTITION BY c1, c2, c3 ORDER BY timestamp ), 0)
          FROM mytable
         WHERE measure IS NOT NULL
    )
    SELECT m.c1, m.c2, m.c3, m.timestamp, m.measure, res.result
      FROM mytable m LEFT OUTER JOIN res
        ON m.c1 = res.c1
       AND m.c2 = res.c2
       AND m.c3 = res.c3
       AND m.timestamp = res.timestamp;
    

    输出

    | c1 | c2 |  c3 |     timestmp | measure | result |
    |----|----|-----|--------------|---------|--------|
    |  A | AA | AAA | 201804200000 |      20 |     20 |
    |  A | AA | AAA | 201804200015 |       2 |     22 |
    |  A | AA | AAA | 201804200030 |       5 |      7 |
    |  A | AA | AAA | 201804200045 |  (null) | (null) |
    |  A | AA | AAA | 201804200100 |  (null) | (null) |
    |  A | AA | AAA | 201804200115 |      12 |     17 |
    |  A | AA | AAA | 201804202345 |      20 |     32 |
    |  B | BB | BBB | 201804200000 |       8 |      8 |
    |  B | BB | BBB | 201804200015 |  (null) | (null) |
    |  B | BB | BBB | 201804200030 |       1 |      9 |
    

    希望这会有所帮助。

    【讨论】:

    • Lag 只带上一个。 OP 想要前一个非空值。检查行17 (12+5)
    • 我在 CTE 中排除 NULL
    • 有错,第一行应该是20,不是null?
    • @JuanCarlosOropeza,也许你错过了我添加COALESCE()的编辑?
    • 感谢您顺便把演示放在一起
    猜你喜欢
    • 2015-09-29
    • 2018-03-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    相关资源
    最近更新 更多