【问题标题】:Oracle sequence generation based on the columns present in the same table基于同一表中存在的列的 Oracle 序列生成
【发布时间】:2014-10-31 13:26:19
【问题描述】:

我正在尝试使用 oracle 中的分析功能生成序列。但是,我的序列取决于表 PROD_INFO 中的两列。列名是 PROD_ID 和 BILLING_NO。对于同一个 PROD_ID,可以有多个 BILLING_NO。 BILLING_NO 也可以有 NULL 值。我需要根据以下逻辑生成 SEQUENCE。

  1. 对于第一组 PROD_ID、BILLING_NO 组合,我需要增加 SEQUENCE,如 2000、2010、2020 等,直到找到具有相同 PROD_ID 的不同 BILLING_NO。
  2. 如果是不同的BILLING_NO,我需要输入序列为3000、3010、3020等
  3. 当 PROD_ID 更改时,我需要将 BILLING_NO 的序列更改为 2000、2010、2020 等。输出显示在下表中。
PROD_ID BILLING_NO  SEQUENCE    QUANTITY

1-7OR   AB1     2000        80

1-7OR   AB1     2010        2

1-7OR   AB1     2020        30

1-7OR   NULL    2030        10

1-7OR   AB2     3000        15

1-7OR   AB2     3010        15

1-7OR   AB2     3020        15

1-7OR   AB2     3030        15

1-7OR   NULL    3040        15

1-7OR   NULL    3050        15

1-7OR   AB3     4000        15

1-7OR   AB3     4010        15

1-7OR   AB3     4020        15

1-9ER   UC1     2000        50

1-9ER   UC1     2010        90

1-9ER   UC1     2020        35

1-9ER   UC1     2030        63

1-9ER   NULL    2040        41

1-9ER   UC2     3000        75

1-9ER   UC2     3010        75

1-9ER   UC2     3020        90

1-9ER   UC2     3030        90

P.S:我在上面的输出中用 'NULL' 描述了 NULL 值。

我目前正在使用以下分析函数。但是它不会更改为 3000、3010 等、4000、4010 等,而是重复 2000、2010、2020 等。

SELECT   PROD_ID,
    BILLING_NO,
    2000 + ROW_NUMBER() OVER (PARTITION BY PROD_ID, BILLING_NO ORDER BY BILLING_NO) * 10 AS SEQUENCE,
    QUANTITY
FROM    PROD_INFO;

那么,请您帮我实现上述结果。

谢谢!

【问题讨论】:

  • 好问题。您需要使用analytic 函数dense_rankrow_number。检查我的答案。

标签: sql oracle sequence


【解决方案1】:
--The query you need
SELECT PROD_ID,
  BILLING_NO,
  (DENSE_RANK() OVER (PARTITION BY prod_id ORDER BY PROD_ID, BILLING_NO) + 1) * 1000 
  + 
  ROW_NUMBER() OVER (PARTITION BY PROD_ID, BILLING_NO ORDER BY BILLING_NO) * 10 AS sequence,
  QUANTITY
FROM PROD_INFO
/

您需要使用ANALYTIC 函数DENSE_RANKROW_NUMBER

让我们用一个测试用例来检查一下,

SQL> WITH DATA AS(
  2  SELECT '1-7OR'  PROD_ID,   'AB1'    BILLING_NO FROM DUAL UNION ALL
  3  SELECT '1-7OR'  PROD_ID,   'AB1'        BILLING_NO FROM DUAL UNION ALL
  4  SELECT '1-7OR'  PROD_ID,   'AB1'      BILLING_NO FROM DUAL UNION ALL
  5  SELECT '1-7OR'  PROD_ID,   NULL       BILLING_NO FROM DUAL UNION ALL
  6  SELECT '1-7OR'  PROD_ID,   'AB2'       BILLING_NO FROM DUAL UNION ALL
  7  SELECT '1-7OR'  PROD_ID,   'AB2'        BILLING_NO FROM DUAL UNION ALL
  8  SELECT '1-7OR'  PROD_ID,   'AB2'         BILLING_NO FROM DUAL UNION ALL
  9  SELECT '1-7OR'  PROD_ID,   'AB2'         BILLING_NO FROM DUAL UNION ALL
 10  SELECT '1-7OR'  PROD_ID,   NULL        BILLING_NO FROM DUAL UNION ALL
 11  SELECT '1-7OR'  PROD_ID,   NULL       BILLING_NO FROM DUAL UNION ALL
 12  SELECT '1-7OR'  PROD_ID,   'AB3'         BILLING_NO FROM DUAL UNION ALL
 13  SELECT '1-7OR'  PROD_ID,   'AB3'        BILLING_NO FROM DUAL UNION ALL
 14  SELECT '1-7OR'  PROD_ID,   'AB3'         BILLING_NO FROM DUAL UNION ALL
 15  SELECT '1-9ER'  PROD_ID,   'UC1'         BILLING_NO FROM DUAL UNION ALL
 16  SELECT '1-9ER'  PROD_ID,   'UC1'        BILLING_NO FROM DUAL UNION ALL
 17  SELECT '1-9ER'  PROD_ID,   'UC1'        BILLING_NO FROM DUAL UNION ALL
 18  SELECT '1-9ER'  PROD_ID,   'UC1'        BILLING_NO FROM DUAL UNION ALL
 19  SELECT '1-9ER'  PROD_ID,   NULL       BILLING_NO FROM DUAL UNION ALL
 20  SELECT '1-9ER'  PROD_ID,   'UC2'      BILLING_NO FROM DUAL UNION ALL
 21  SELECT '1-9ER'  PROD_ID,   'UC2'      BILLING_NO FROM DUAL UNION ALL
 22  SELECT '1-9ER'  PROD_ID,   'UC2'        BILLING_NO FROM DUAL UNION ALL
 23  SELECT '1-9ER'  PROD_ID,   'UC2'         BILLING_NO FROM DUAL
 24  )
 25  --The query you need
 26  SELECT PROD_ID,
 27    BILLING_NO,
 28    (DENSE_RANK() OVER (PARTITION BY prod_id ORDER BY PROD_ID, BILLING_NO) + 1) * 1000
 29    +
 30    ROW_NUMBER() OVER (PARTITION BY PROD_ID, BILLING_NO ORDER BY BILLING_NO) * 10 AS sequence
 31  FROM data
 32  /

PROD_ BIL             SEQUENCE
----- --- --------------------
1-7OR AB1                 2010
1-7OR AB1                 2020
1-7OR AB1                 2030
1-7OR AB2                 3010
1-7OR AB2                 3020
1-7OR AB2                 3030
1-7OR AB2                 3040
1-7OR AB3                 4010
1-7OR AB3                 4020
1-7OR AB3                 4030
1-7OR                     5010
1-7OR                     5020
1-7OR                     5030
1-9ER UC1                 2010
1-9ER UC1                 2020
1-9ER UC1                 2030
1-9ER UC1                 2040
1-9ER UC2                 3010
1-9ER UC2                 3020
1-9ER UC2                 3030
1-9ER UC2                 3040
1-9ER                     4010

22 rows selected.

SQL>

注意窗口函数将所有 NULL 保持在一起。

【讨论】:

  • 太棒了,谢谢!我只是稍微调整了您的答案以从 2000 年开始序列。 SELECT PROD_ID, BILLING_NO, (DENSE_RANK() OVER (PARTITION BY prod_id ORDER BY PROD_ID, BILLING_NO) + 1) * 1000 + (ROW_NUMBER() OVER (PARTITION BY PROD_ID, BILLING_NO ORDER BY BILLING_NO) * 10) - 10 作为序列,数量来自 PROD_INFO;
  • 啊,是的,我没有意识到我的解决方案的序列从2010 开始,而不是2000。感谢您的反馈:-)
猜你喜欢
  • 1970-01-01
  • 2020-01-01
  • 2018-11-04
  • 2014-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-12
  • 1970-01-01
相关资源
最近更新 更多