【发布时间】:2020-03-01 07:30:00
【问题描述】:
我正在尝试使用 LAG 获取组中排名第二的行以及前一个(排名第一的)行中的值。
但是,应用条件 where place = 2 会导致结果集的第一行只有 LAG 结果。
包含LEAD 列会导致预期结果显示在LAG 列中。
我使用的是 Oracle 19c,我正在使用的表如下所示:
UKNUM PARTY UKVOTES
----- ------ --------
1 con 6605
1 lab 23745
1 lib 8206
1 plaid 1859
每个uknum 至少有三行,并且所有列都不为空。
这是我的查询,旨在获取第二个放置的行(ukvotes),并为第一个放置的行提供 ukvotes 值:
SELECT
*
FROM
(
SELECT
uknum,
rank() OVER (PARTITION BY uknum ORDER BY ukvotes DESC) AS place,
lag(ukvotes) OVER (PARTITION BY uknum ORDER BY ukvotes DESC) AS lag
FROM
ukresults
)
WHERE
place = 2
AND uknum BETWEEN 1 AND 5;
这会产生以下结果:
UKNUM PLACE LAG
---------- ---------- ----------
1 2 23745
2 2
3 2
4 2
5 2
我希望对于第 2-5 行,LAG 列中会有一个非空值。
将LEAD 添加到查询会导致LAG 列包含预期结果:
SELECT
*
FROM
(
SELECT
uknum,
rank() OVER (PARTITION BY uknum ORDER BY ukvotes DESC) AS place,
lag(ukvotes) OVER (PARTITION BY uknum ORDER BY ukvotes DESC) AS lag,
lead(ukvotes) OVER (PARTITION BY uknum ORDER BY ukvotes DESC) AS lead
FROM
ukresults
)
WHERE
place = 2
AND uknum BETWEEN 1 AND 5;
UKNUM PLACE LAG LEAD
---------- ---------- ---------- ----------
1 2 23745 6605
2 2 19262 7426
3 2 15393 10372
4 2 31288 6070
5 2 24148 11599
我很困惑为什么第一个查询没有产生预期的结果,所有行的值都是LAG。
Here’s a DBFiddle with the data and the queries loaded.
更新:这里是来自 Oracle 19c 的查询计划,首先用于仅使用 LAG 的查询,然后是单独使用 LEAD 或 LAG 和 LEAD 一起使用的查询计划(对于包含LEAD)。
LAG 唯一计划:
--------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 197 | 7683 | 5 (20)| 00:00:01 |
|* 1 | VIEW | | 197 | 7683 | 5 (20)| 00:00:01 |
|* 2 | WINDOW SORT PUSHED RANK| | 197 | 1773 | 5 (20)| 00:00:01 |
| 3 | TABLE ACCESS CLUSTER | UKRESULTS | 197 | 1773 | 4 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | UKNUMX | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("PLACE"=2)
2 - filter(RANK() OVER ( PARTITION BY "UKNUM" ORDER BY
INTERNAL_FUNCTION("UKVOTES") DESC )<=2)
4 - access("UKNUM"<=50)
仅限LEAD / LAG 和LEAD 计划:
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 197 | 7683 | 5 (20)| 00:00:01 |
|* 1 | VIEW | | 197 | 7683 | 5 (20)| 00:00:01 |
| 2 | WINDOW SORT | | 197 | 1773 | 5 (20)| 00:00:01 |
| 3 | TABLE ACCESS CLUSTER| UKRESULTS | 197 | 1773 | 4 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | UKNUMX | 1 | | 2 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("PLACE"=2)
4 - access("UKNUM"<=50)
【问题讨论】:
-
显示每一行的投票数。原始数据也会有所帮助。您可以设置某种 dbfiddle。
-
您的查询似乎没有产生您让我们期望的结果,但也许我没有正确的数据。 See this dbfiddle
-
DBFiddle 可在此处获得:dbfiddle.uk/…@BobJarvis 它仅提供第一行的结果,其余为 null。
-
啊,非常好 - 感谢 dbfiddle。 :-)