oracle 如何缩短使用CONNECT BY和LEVEL子句的查询的处理时间

fcipmucu  于 2023-04-20  发布在  Oracle
关注(0)|答案(1)|浏览(261)

我想知道是否有一种方法可以重写以下Oracle SQL脚本以获得更好的处理时间。当前版本非常慢,并且无法处理我正在处理的较大数据集。
我试图分配一个数字给每个客户的基础上有多少年,他们一直与企业.我需要它返回每个客户与他们的起始年份,然后计数到现在.我已经尝试解释它下面.
对于一个客户已经与企业5年我希望脚本返回以下内容
| 客户代码|年份|年数|
| --------------|--------------|--------------|
| CUST1|2018年|0|
| CUST1|2019年|1|
| CUST1|2020年|二|
| CUST1|2021|三|
| CUST1|2022年|四|
| CUST1|二零二三年|五|
我尝试使用CONNECT BY和LEVEL,但时间太长。

YEARS AS 
(
  SELECT CUSTOMER_CODE, (MIN_YR+LEVEL-1) AS YR_NUM, ((MIN_YR+LEVEL-1) - MIN_YR) AS YRS
  FROM
(
  SELECT CUSTOMER_CODE, EXTRACT (YEAR FROM MIN_DT) MIN_YR , '2023' AS CUR_YR
  FROM
  (
    SELECT REV.CUSTOMER_CODE, MIN(REV.ORDER_DATE) AS MIN_DT
    FROM REVENUE_TABLE REV 
    JOIN CUSTOMER_DETAILS ACC ON REV.CUSTOMER_CODE = ACC.CUSTOMER_CODE
    GROUP BY REV.CUSTOMER_CODE
  )
)
  CONNECT BY LEVEL <= CUR_YR-MIN_YR
)

SELECT * FROM YEARS

我已经使用CONNECT BY和LEVEL子句为每个客户生成一个数字,表示与该业务的年数。脚本正在工作,但它需要太长的时间才能使用。我让脚本运行了大约4小时,但它没有完成运行。数据量太高,无法完成。

3mpgtkmj

3mpgtkmj1#

从最里面的查询开始,包含customer_details表可能没有任何用处-您没有使用其中的任何内容。它唯一可能的用途是过滤掉不在customer_details表中的revenue元素,但我真的怀疑您正在尝试这样做。
一种更简洁的方法是使用递归CTE,它从每个客户的最早日期开始,然后每次向前滚动一年,直到它等于当前年份。

With Recursive Years AS (
    SELECT REV.CUSTOMER_CODE, Year(MIN(REV.ORDER_DATE)) AS Year_Number
    FROM REVENUE_TABLE REV 
    GROUP BY REV.CUSTOMER_CODE
  UNION ALL
    Select CUSTOMER_CODE, Year_Number+1
    From Years
    Where Year_Number < Year(Current_Date)
)
Select * from Years

现在,您可以将表的其余部分连接到该结果,或者对它执行任何其他需要的操作。

相关问题