我继承了这个查询来重建它:
SELECT a.poclcdde,
a.poclnpol,
a.poclcdce,
a.poclcdcl,
a.poclnuor
FROM dtpocl a
WHERE a.poclcdre = '02'
AND a.poclxope IN ('01', '02')
AND a.poclnuor =
(SELECT MAX (b.poclnuor)
FROM dtpocl b
WHERE b.poclcdde = a.poclcdde
AND b.poclnpol = a.poclnpol
AND b.poclcdce = a.poclcdce
AND b.poclcdre = '02'
AND b.poclxope IN ('01', '02')
AND NVL (b.poclfecb, 99999999) =
(SELECT MAX (NVL (c.poclfecb, 99999999))
FROM dtpocl c
WHERE c.poclcdde = b.poclcdde
AND c.poclnpol = b.poclnpol
AND c.poclcdce = b.poclcdce
AND c.poclcdre = '02'
AND c.poclxope IN ('01', '02')))
我有这个解释计划:
Plan hash value: 94095463
--------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6293 | 497K| | 53434 (3)| 00:00:03 |
| 1 | NESTED LOOPS | | | | | | |
| 2 | NESTED LOOPS | | 6293 | 497K| | 53434 (3)| 00:00:03 |
| 3 | VIEW | VW_SQ_2 | 12340 | 626K| | 41045 (4)| 00:00:02 |
| 4 | HASH GROUP BY | | 12340 | 602K| 792K| 41045 (4)| 00:00:02 |
|* 5 | HASH JOIN | | 12340 | 602K| 47M| 40911 (4)| 00:00:02 |
| 6 | VIEW | VW_SQ_1 | 1555K| 29M| | 23144 (4)| 00:00:01 |
| 7 | HASH GROUP BY | | 1555K| 40M| 65M| 23144 (4)| 00:00:01 |
|* 8 | TABLE ACCESS FULL | DTPOCL | 1555K| 40M| | 12793 (4)| 00:00:01 |
|* 9 | TABLE ACCESS FULL | DTPOCL | 1555K| 44M| | 12801 (4)| 00:00:01 |
|* 10 | INDEX RANGE SCAN | PK_DTPOCL | 1 | | | 1 (0)| 00:00:01 |
|* 11 | TABLE ACCESS BY INDEX ROWID| DTPOCL | 1 | 29 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
5 - access("MAX(NVL(C.POCLFECB,99999999))"=NVL("POCLFECB",'99999999') AND
"ITEM_1"="POCLCDDE" AND "ITEM_2"="POCLNPOL" AND "ITEM_3"="POCLCDCE")
8 - filter("POCLCDRE"='02' AND ("POCLXOPE"='01' OR "POCLXOPE"='02'))
9 - filter("POCLCDRE"='02' AND ("POCLXOPE"='01' OR "POCLXOPE"='02'))
10 - access("ITEM_4"="POCLCDDE" AND "ITEM_5"="POCLNPOL" AND "ITEM_6"="POCLCDCE" AND
"POCLNUOR"="MAX(B.POCLNUOR)")
11 - filter("POCLCDRE"='02' AND ("POCLXOPE"='01' OR "POCLXOPE"='02'))
乍一看,我可以想象这是一个错误的查询,因为:为什么我们需要为同一个表执行两个以上的子查询?
我需要的是来自dtpocl
表(具有此条件a.poclcdre = '02' AND a.poclxope IN ('01', '02')
)的所有记录,其最大poclnuor
和最大日期poclfecb
。
我试图在同一个查询中对两个聚合函数进行分组,如下所示:
SELECT a.poclcdde,
a.poclnpol,
a.poclcdce,
a.poclcdcl,
MAX (a.poclnuor),
MAX (NVL (a.poclfecb, 99999999))
FROM dtpocl a
WHERE a.poclcdre = '02' AND a.poclxope IN ('01', '02')
GROUP BY a.poclcdde,
a.poclnpol,
a.poclcdce,
a.poclcdcl
但是我得到的记录多于原始查询,成本为25.654。 dtpocl
表有3.025.510行。
我们可以采取哪些措施来提高性能和查询可读性?感谢。
答案 0 :(得分:2)
您可以使用分析功能查找您感兴趣的poclnuor
。
SELECT
*
FROM
(
SELECT
dtpocl.*,
MAX(poclnuor)
KEEP (DENSE_RANK FIRST ORDER BY poclfecb DESC NULLS FIRST)
OVER (PARTITION BY poclcdde, poclnpol, poclcdce)
AS target_poclnuor
FROM
dtpocl
WHERE
poclcdre = '02'
AND poclxope IN ('01', '02')
)
sorted
WHERE
poclnuor = target_poclnuor
我从这里得到了语法...... https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions056.htm
您可能想要一个涵盖(poclcdde, poclnpol, poclcdce, poclfecb DESC, poclnuor DESC)
编辑: OP确认PK为(poclcdde, poclnpol, poclcdce, poclnuor)
我不确定这是否更好,但知道PK确实意味着这是另一种选择......
SELECT
poclcdde,
poclnpol,
poclcdce,
MAX(poclcdcl)
KEEP (RANK FIRST
ORDER BY poclfecb DESC NULLS FIRST,
poclnuor DESC
)
AS poclcdcl,
MAX(poclnuor)
KEEP (RANK FIRST
ORDER BY poclfecb DESC NULLS FIRST,
poclnuor DESC
)
AS poclnuor
FROM
dtpocl
WHERE
poclcdre = '02'
AND poclxope IN ('01', '02')
GROUP BY
poclcdde,
poclnpol,
poclcdce
或者...
SELECT
sorted.*
FROM
(
SELECT
ROW_NUMBER()
OVER (PARTITION BY poclcdde, poclnpol, poclcdce
ORDER BY poclfecb DESC NULLS FIRST,
poclnuor DESC
)
AS seqnum
dtpocl.*
FROM
dtpocl
WHERE
poclcdre = '02'
AND poclxope IN ('01', '02')
)
sorted
WHERE
seqnum = 1
答案 1 :(得分:0)
这个怎么样?
-- PK is poclcdde, poclnpol, poclcdce & poclnuor
SELECT a.poclcdde,
a.poclnpol,
a.poclcdce,
a.poclcdcl,
a.poclnuor,
a.poclfecb
FROM dtpocl a
WHERE a.poclcdre = '02'
AND a.poclxope IN ('01', '02')
AND a.poclnuor =
(SELECT MAX (b.poclnuor)
FROM dtpocl b
WHERE b.poclcdde = a.poclcdde
AND b.poclnpol = a.poclnpol
AND b.poclcdce = a.poclcdce
AND b.poclnuor = a.poclnuor
AND b.poclcdre = a.poclcdre
AND b.poclxope = a.poclxope)
AND NVL (a.poclfecb, 99999999) = -- Here you can only use a.poclfecb and not b.poclfecb
(SELECT MAX (NVL (c.poclfecb, 99999999))
FROM dtpocl c
WHERE c.poclcdde = a.poclcdde
AND c.poclnpol = a.poclnpol
AND c.poclcdce = a.poclcdce
AND c.poclnuor = a.poclnuor
AND c.poclcdre = a.poclcdre
AND c.poclxope = a.poclxope)