【问题标题】:Oracle - Increment valueOracle - 增量值
【发布时间】:2016-10-25 07:21:16
【问题描述】:

我有一个保存客户发票数据的表格。我试图通过创建结转柜台来查找特定交易类型在客户发票上出现的月份数。如果事务不再存在,计数器应重置为零。

表:

+------------+-------------+----------------+----------+
| Invoice_Id | Customer_id | Transaction_id | Sequence |
+------------+-------------+----------------+----------+
|     253442 |       23334 |                |        1 |
|     253443 |       23334 |                |        2 |
|     253444 |       23334 |                |        3 |
|     253445 |       23334 |                |        4 |
|    1050646 |       23334 |                |        5 |
|    8457065 |       23334 |                |        6 |
|    9052920 |       23334 |                |        7 |
|    9333044 |       23334 |                |        8 |
|    9616743 |       23334 |                |        9 |
|    9894491 |       23334 |                |       10 |
|   10186697 |       23334 |                |       11 |
|   10490938 |       23334 |                |       12 |
|   10803986 |       23334 |       69709477 |       13 |
|   11132317 |       23334 |       72103163 |       14 |
|   11444923 |       23334 |                |       15 |
+------------+-------------+----------------+----------+

我想要达到的目标:

+------------+-------------+----------------+----------+-----------+
| Invoice_Id | Customer_id | Transaction_id | Sequence | Carryover |
+------------+-------------+----------------+----------+-----------+
|     253442 |       23334 |                |        1 |         0 |
|     253443 |       23334 |                |        2 |         0 |
|     253444 |       23334 |                |        3 |         0 |
|     253445 |       23334 |                |        4 |         0 |
|    1050646 |       23334 |                |        5 |         0 |
|    8457065 |       23334 |                |        6 |         0 |
|    9052920 |       23334 |                |        7 |         0 |
|    9333044 |       23334 |                |        8 |         0 |
|    9616743 |       23334 |                |        9 |         0 |
|    9894491 |       23334 |                |       10 |         0 |
|   10186697 |       23334 |                |       11 |         0 |
|   10490938 |       23334 |                |       12 |         0 |
|   10803986 |       23334 |       69709477 |       13 |         1 |
|   11132317 |       23334 |       72103163 |       14 |         2 |
|   11444923 |       23334 |                |       15 |         0 |
+------------+-------------+----------------+----------+-----------+

我假设我可以使用分析函数/Oracle cte?

谢谢!

添加:

transaction_count = 0 时重置的 transaction_count 的累计和。

+------------+-------------+-------------------+----------+-----------+
| Invoice_Id | Customer_id | Transaction_Count | Sequence | Carryover |
+------------+-------------+-------------------+----------+-----------+
|     253442 |       23334 |                 0 |        1 |         0 |
|     253443 |       23334 |                 0 |        2 |         0 |
|     253444 |       23334 |                 1 |        3 |         1 |
|     253445 |       23334 |                 1 |        4 |         2 |
|    1050646 |       23334 |                 0 |        5 |         0 |
|    8457065 |       23334 |                 0 |        6 |         0 |
|    9052920 |       23334 |                 2 |        7 |         2 |
|    9333044 |       23334 |                 1 |        8 |         3 |
|    9616743 |       23334 |                 0 |        9 |         0 |
|    9894491 |       23334 |                 0 |       10 |         0 |
|   10186697 |       23334 |                 0 |       11 |         0 |
|   10490938 |       23334 |                 0 |       12 |         0 |
|   10803986 |       23334 |                 1 |       13 |         1 |
|   11132317 |       23334 |                 1 |       14 |         2 |
|   11444923 |       23334 |                 0 |       15 |         0 |
+------------+-------------+-------------------+----------+-----------+

【问题讨论】:

    标签: oracle11g increment analytic-functions


    【解决方案1】:

    假设我正确理解了您的要求,这里有一种方法,它使用Tabibitosan method 根据连续的 null/not-null tr​​ansaction_ids 对数据进行“分组”。一旦我们有了这些信息,我们就可以根据 transaction_id 是否为空来执行条件 row_number()。

    WITH sample_data AS (SELECT 253442 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 1 seq FROM dual UNION ALL
                         SELECT 253443 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 2 seq FROM dual UNION ALL
                         SELECT 253444 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 3 seq FROM dual UNION ALL
                         SELECT 253445 Invoice_Id, 23334 Customer_id, 123 Transaction_id, 4 seq FROM dual UNION ALL
                         SELECT 1050646 Invoice_Id, 23334 Customer_id, 456 Transaction_id, 5 seq FROM dual UNION ALL
                         SELECT 8457065 Invoice_Id, 23334 Customer_id, 789 Transaction_id, 6 seq FROM dual UNION ALL
                         SELECT 9052920 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 7 seq FROM dual UNION ALL
                         SELECT 9333044 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 8 seq FROM dual UNION ALL
                         SELECT 9616743 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 9 seq FROM dual UNION ALL
                         SELECT 9894491 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 10 seq FROM dual UNION ALL
                         SELECT 10186697 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 11 seq FROM dual UNION ALL
                         SELECT 10490938 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 12 seq FROM dual UNION ALL
                         SELECT 10803986 Invoice_Id, 23334 Customer_id, 69709477 Transaction_id, 13 seq FROM dual UNION ALL
                         SELECT 11132317 Invoice_Id, 23334 Customer_id, 72103163 Transaction_id, 14 seq FROM dual UNION ALL
                         SELECT 11444923 Invoice_Id, 23334 Customer_id, NULL Transaction_id, 15 seq FROM dual)
    -- end of mimicking your data in a "table" called sample_data
    -- you wouldn't need this - you'd just select from your table directly in the sql below:
    SELECT invoice_id,
           customer_id,
           transaction_id,
           seq,
           CASE WHEN transaction_id is not NULL THEN
                     row_number() OVER (PARTITION BY customer_id, grp ORDER BY seq)
                ELSE 0
           END carryover
    FROM   (SELECT invoice_id,
                   customer_id,
                   transaction_id,
                   seq,
                   row_number() OVER (PARTITION BY customer_id ORDER BY seq)
                     - row_number() OVER (PARTITION BY customer_id, CASE WHEN transaction_id IS NULL THEN 0 ELSE 1 END ORDER BY seq) grp
            FROM   sample_data)
    ORDER BY customer_id, seq;
    
    INVOICE_ID CUSTOMER_ID TRANSACTION_ID        SEQ  CARRYOVER
    ---------- ----------- -------------- ---------- ----------
        253442       23334                         1          0
        253443       23334                         2          0
        253444       23334                         3          0
        253445       23334            123          4          1
       1050646       23334            456          5          2
       8457065       23334            789          6          3
       9052920       23334                         7          0
       9333044       23334                         8          0
       9616743       23334                         9          0
       9894491       23334                        10          0
      10186697       23334                        11          0
      10490938       23334                        12          0
      10803986       23334       69709477         13          1
      11132317       23334       72103163         14          2
      11444923       23334                        15          0
    

    附加要求:

    WITH sample_data AS (SELECT 253442 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 1 seq FROM dual UNION ALL
                         SELECT 253443 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 2 seq FROM dual UNION ALL
                         SELECT 253444 Invoice_Id, 23334 Customer_id, 1 Transaction_Count, 3 seq FROM dual UNION ALL
                         SELECT 253445 Invoice_Id, 23334 Customer_id, 1 Transaction_Count, 4 seq FROM dual UNION ALL
                         SELECT 1050646 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 5 seq FROM dual UNION ALL
                         SELECT 8457065 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 6 seq FROM dual UNION ALL
                         SELECT 9052920 Invoice_Id, 23334 Customer_id, 2 Transaction_Count, 7 seq FROM dual UNION ALL
                         SELECT 9333044 Invoice_Id, 23334 Customer_id, 1 Transaction_Count, 8 seq FROM dual UNION ALL
                         SELECT 9616743 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 9 seq FROM dual UNION ALL
                         SELECT 9894491 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 10 seq FROM dual UNION ALL
                         SELECT 10186697 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 11 seq FROM dual UNION ALL
                         SELECT 10490938 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 12 seq FROM dual UNION ALL
                         SELECT 10803986 Invoice_Id, 23334 Customer_id, 1 Transaction_Count, 13 seq FROM dual UNION ALL
                         SELECT 11132317 Invoice_Id, 23334 Customer_id, 1 Transaction_Count, 14 seq FROM dual UNION ALL
                         SELECT 11444923 Invoice_Id, 23334 Customer_id, 0 Transaction_Count, 15 seq FROM dual)
    -- end of mimicking your data in a "table" called sample_data
    -- you wouldn't need this - you'd just select from your table directly in the sql below:
    SELECT invoice_id,
           customer_id,
           Transaction_Count,
           seq,
           SUM(transaction_count) OVER (PARTITION BY customer_id,
                                                     CASE WHEN Transaction_Count = 0 THEN 0 ELSE 1 END, 
                                                     grp
                                        ORDER BY seq) carryover
    FROM   (SELECT invoice_id,
                   customer_id,
                   Transaction_Count,
                   seq,
                   row_number() OVER (PARTITION BY customer_id
                                      ORDER BY seq)
                     - row_number() OVER (PARTITION BY customer_id,
                                                       CASE WHEN Transaction_Count = 0 THEN 0 ELSE 1 END
                                          ORDER BY seq) grp
            FROM   sample_data)
    ORDER BY customer_id, seq;
    
    INVOICE_ID CUSTOMER_ID TRANSACTION_COUNT        SEQ  CARRYOVER
    ---------- ----------- ----------------- ---------- ----------
        253442       23334                 0          1          0
        253443       23334                 0          2          0
        253444       23334                 1          3          1
        253445       23334                 1          4          2
       1050646       23334                 0          5          0
       8457065       23334                 0          6          0
       9052920       23334                 2          7          2
       9333044       23334                 1          8          3
       9616743       23334                 0          9          0
       9894491       23334                 0         10          0
      10186697       23334                 0         11          0
      10490938       23334                 0         12          0
      10803986       23334                 1         13          1
      11132317       23334                 1         14          2
      11444923       23334                 0         15          0
    

    它使用了与原始解决方案非常相似的概念,除了在最终 sum() 分析函数的 partition by 子句中添加了对零或非零事务计数的检查,我们不再需要 case 语句输出 0或总和。

    希望您能说出我必须进行哪些调整 - 基本上,检查 transaction_id 是否为 null/not null 必须更改为 transaction_count = 0/!= 0,再加上将 row_number() 更改为 sum(transaction_count) 加上上述对 partition by 子句的更改。我敢肯定,如果您还没有考虑过,您会得出相同的结论,如果您还没有! *{:-)

    【讨论】:

    • 感谢您的出色回答。假设每张发票的 transaction_id 被替换为非空 transaction_count。结转不是从 1 开始,而是从 transaction_count 开始。然后将结转计算为 transaction_count 前一行 + transaction count 当前行。交易计数为 0 将与之前一样将结转重置为 0。这可以通过使用 LAG 分析功能实现吗?
    • 我不确定我明白你的意思。请更新您问题中的示例数据和预期输出以说明您的意思。从表面上看,我认为你只需要一个sum() 代替row_number(),就可以进行累计。但是,如果没有看到数据是什么样的,以及预期的输出,很难说是不是这样。
    • 没有给出预期的结果。上面更新了最初的问题。
    • 我想我明白了:transaction_count 0 的情况然后 transaction_count + lag(transaction_count,1) over (order by customer_id,sequence) Else 0 end as carryover
    • 无需延迟;我已更新我的答案以使用累积总和而不是之前使用的 row_number。
    猜你喜欢
    • 2012-04-01
    • 2019-07-22
    • 2014-05-08
    • 1970-01-01
    • 1970-01-01
    • 2019-08-29
    • 2011-09-01
    • 2013-06-06
    • 1970-01-01
    相关资源
    最近更新 更多