2016-10-25 41 views
1

我有一张持有客户发票数据的表格。我试图通过创建一个结转计数器来查找客户的发票上有多少个月特定的交易类型。如果交易不再存在,计数器应重置为零。甲骨文 - 增量值

表:

+------------+-------------+----------------+----------+ 
| 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的带复位

累积总和时transaction_count = 0

+------------+-------------+-------------------+----------+-----------+ 
| 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 | 
+------------+-------------+-------------------+----------+-----------+ 

回答

1

假设我正确理解你的需求,这里有一个方法,它使用Tabibitosan method为“集团”数据基于onsecutive null/not-null tr​​ansaction_ids。一旦我们有了这些信息,我们就可以根据transaction_id是否为null来做一个条件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 

它采用了非常相似的概念到原来的溶液,除了通过添加对零或非零transaction_count检查到由子句分区最后的sum()分析函数中,我们不再需要case语句来输出0或总和。

希望你能告诉我有什么调整,以使 - 基本上,对于TRANSACTION_ID支票为空/不为空,就必须改变以transaction_count = 0/= 0,加row_number()sum(transaction_count)的变化,加上前面提到的改变!到分区的条款。我敢肯定,如果你还有更多的想法,如果还没有的话,你会得出同样的结论! * {:-)

+0

谢谢你的出色答案。假设每个发票的transaction_id被替换为非空的transaction_count。结转将代替从1开始,从transaction_count开始。随后将结转计算为transaction_count上一行+交易计数当前行。事务计数中的0将像以前一样将残留重置为0.这是否可以通过使用LAG分析函数来实现? – MrM

+0

我不确定我明白你的意思。请更新您问题中的示例数据和预期输出以说明您的意思。从表面上看,我认为你只需要一个'sum()'来代替'row_number()'来做一个累计和。但是,如果没有看到数据的外观以及预期的输出结果,很难说是否如此。 – Boneist

+0

没有给出预期的结果。上面更新的初始问题。 – MrM