在表格中,我需要根据列将2条记录合并为一条记录 (在这种情况下,列1.WORK_ORDER_NUM,2.ESN 3.PLANT 4. REMD_PART_NUM 5. REMD_PART_SERIAL)。如果这5列相等,那么我必须在其他列中使用Aggregate函数将其作为一个记录 在这种情况下,列是LLP_TRACKD_PART_IND,REMD_PART_TSN和 REMD_PART_CSN]。
这是我尝试过的:
SELECT decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)PLANT,
COUNT(*) RECORD_COUNT,
COUNT(DISTINCT OFF.REMD_PART_NUM) REMD_PART_NUM_COUNT,
COUNT(DISTINCT OFF.REMD_PART_SERIAL) REMD_PART_SER_NUM_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'LL',LLP_TRACKD_PART_IND,NULL)) LL_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'LR',LLP_TRACKD_PART_IND,NULL)) LR_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'TR',LLP_TRACKD_PART_IND,NULL)) TR_COUNT,
SUM(OFF.REMD_PART_QTY) TOTAL_REMD_PART_QTY,
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_TSN AS NUMBER)
ELSE 0
END
)) TOTAL_TSN,
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_CSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_CSN AS NUMBER)
ELSE 0
END
)) TOTAL_CSN
FROM (with t as ( SELECT distinct PLANT,
WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,REMD_PART_IIN,
LLP_TRACKD_PART_IND,
REMD_PART_QTY,REMD_PART_TSN,REMD_PART_CSN,REMD_PART_TSO,REMD_PART_CSO
,REMD_PART_TSC,REMD_PART_CSC,REMD_CYCLE_REMAIN
FROM <TABLE1>
WHERE
REMD_PART_NUM is not null
)
select DISTINCT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL
,REMD_PART_IIN
,(select max(LLP_TRACKD_PART_IND) from t bb where aa.PLANT=bb.PLANT and
aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL) LLP_TRACKD_PART_IND
,REMD_PART_QTY
,(select max(REMD_PART_TSN) from t bb where aa.PLANT=bb.PLANT and
aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL) REMD_PART_TSN
,
(select max(REMD_PART_CSN) from t bb where aa.PLANT=bb.PLANT and
aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL) REMD_PART_CSN
from t aa) OFF
WHERE
REMD_PART_NUM is not null
GROUP BY decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)
完成需要大约8个小时。还有其他方法可以更快地完成它。 It took 8 hours to complete
答案 0 :(得分:1)
从更好的查询格式开始,它可以让您轻松理解代码并注意重复的模式:
SELECT decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)PLANT,
COUNT(*) RECORD_COUNT,
COUNT(DISTINCT OFF.REMD_PART_NUM) REMD_PART_NUM_COUNT,
COUNT(DISTINCT OFF.REMD_PART_SERIAL) REMD_PART_SER_NUM_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'LL',LLP_TRACKD_PART_IND,NULL)) LL_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'LR',LLP_TRACKD_PART_IND,NULL)) LR_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'TR',LLP_TRACKD_PART_IND,NULL)) TR_COUNT,
SUM(OFF.REMD_PART_QTY) TOTAL_REMD_PART_QTY,
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_TSN AS NUMBER)
ELSE 0
END
)) TOTAL_TSN,
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_CSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_CSN AS NUMBER)
ELSE 0
END
)) TOTAL_CSN
FROM (
with t as (
SELECT distinct PLANT, WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,REMD_PART_IIN,
LLP_TRACKD_PART_IND,
REMD_PART_QTY,REMD_PART_TSN,REMD_PART_CSN,REMD_PART_TSO,REMD_PART_CSO
,REMD_PART_TSC,REMD_PART_CSC,REMD_CYCLE_REMAIN
FROM <TABLE1>
WHERE REMD_PART_NUM is not null
)
select DISTINCT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL
,REMD_PART_IIN
,( select max(LLP_TRACKD_PART_IND)
from t bb
where aa.PLANT=bb.PLANT
and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL
) LLP_TRACKD_PART_IND
,REMD_PART_QTY
,( select max(REMD_PART_TSN) from t bb
where aa.PLANT=bb.PLANT
and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL
) REMD_PART_TSN
,
( select max(REMD_PART_CSN) from t bb
where aa.PLANT=bb.PLANT
and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL
) REMD_PART_CSN
from t aa
) OFF
WHERE REMD_PART_NUM is not null
GROUP BY decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)
;
您将看到以下模式重复3次(3个几乎相同的子查询):
select max( some_field )
from t bb
where aa.PLANT=bb.PLANT
and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM
and aa.ESN=bb.ESN
and aa.REMD_PART_NUM=bb.REMD_PART_NUM
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL
您还可以轻松地看到此查询中有3个非常昂贵的排序操作 - 最内层子查询中的一个DISTINCT,然后是另一个子查询中的另一个DISTINCT,最后是顶级查询中的GROUP BY操作(一种DISTINCT)
仅查看您的查询,可以通过这种方式轻松地使用分析函数消除一种类型(DISTINCT):
SELECT * FROM (
SELECT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,
REMD_PART_IIN, REMD_PART_QTY,
max( LLP_TRACKD_PART_IND ) over
(partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL)
as LLP_TRACKD_PART_IND,
max( REMD_PART_TSN ) over
(partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL)
as REMD_PART_TSN,
max( REMD_PART_CSN ) over
(partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL)
as REMD_PART_CSN,
row_number() over
(partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL, REMD_PART_IIN, REMD_PART_QTY
order by PLANT) as Rn
FROM TABLE1
WHERE REMD_PART_NUM is not null
)
WHERE rn = 1
所以最终的查询可能是:
SELECT decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)PLANT,
COUNT(*) RECORD_COUNT,
COUNT(DISTINCT OFF.REMD_PART_NUM) REMD_PART_NUM_COUNT,
COUNT(DISTINCT OFF.REMD_PART_SERIAL) REMD_PART_SER_NUM_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'LL',LLP_TRACKD_PART_IND,NULL)) LL_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'LR',LLP_TRACKD_PART_IND,NULL)) LR_COUNT,
COUNT(DECODE(LLP_TRACKD_PART_IND,'TR',LLP_TRACKD_PART_IND,NULL)) TR_COUNT,
SUM(OFF.REMD_PART_QTY) TOTAL_REMD_PART_QTY,
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_TSN AS NUMBER)
ELSE 0
END
)) TOTAL_TSN,
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_CSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_CSN AS NUMBER)
ELSE 0
END
)) TOTAL_CSN
FROM (
SELECT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,REMD_PART_IIN, REMD_PART_QTY,
max( LLP_TRACKD_PART_IND ) over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) as LLP_TRACKD_PART_IND,
max( REMD_PART_TSN ) over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) as REMD_PART_TSN,
max( REMD_PART_CSN ) over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) as REMD_PART_CSN,
row_number() over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL, REMD_PART_IIN, REMD_PART_QTY
order by PLANT) as Rn
FROM TABLE1
WHERE REMD_PART_NUM is not null
)
WHERE rn = 1
GROUP BY decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)
我觉得这个查询可以进一步优化,但需要深入了解表格结构和业务需求知识。
尽管如此,仍有一些微观优化可能 这种模式:
SUM(decode(LLP_TRACKD_PART_IND,null,0,
CASE
WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_TSN AS NUMBER)
ELSE 0
END
)) TOTAL_TSN,
可以替换为:
coalesce(
SUM(
CASE
WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$')
THEN CAST(REMD_PART_TSN AS NUMBER)
ELSE 0
END
), 0
)
由于SUM忽略空值,因此检查每条记录的NULL值是一种浪费。对于少量记录(<1百万)而言并不重要,但对于数以亿计的记录,您可以达到规模效果 - 比如0.05 ms用于检查每条记录乘以10.000.000记录可以给出500秒。