【发布时间】:2013-09-16 03:13:14
【问题描述】:
当我在手动构建的数据集上使用 FIRST_VALUE 时,我得到一个结果,当我在左连接产生的数据集上使用它时,我得到不同的结果 - 即使数据集看起来我包含完全相同的数据值。我用下面的一个简单数据集重现了这个问题。
如果我误解了什么,谁能告诉我?
此 SQL 产生预期结果,即 FIRST_VALUE 为 NULL,LAST_VALUE 为 30。
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
(
SELECT 1 agroup, 10 aval
UNION ALL SELECT 1, NULL
UNION ALL SELECT 1, 30
) T
此 SQL 使用 LEFT JOIN 生成与上述相同的数据集,但 FIRST_VALUE 似乎忽略了 NULL。
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
(
SELECT
T1.agroup,
T1.akey,
T2.aval
FROM
(
SELECT 1 agroup, 1 akey
UNION ALL SELECT 1, 2
UNION ALL SELECT 1, 3
) T1
LEFT JOIN
(
SELECT 1 akey, 10 aval
UNION ALL SELECT 3,30
) T2 ON T1.akey = T2.akey
) T
我还可以证明,当使用表变量和 CTE 时,左连接行为是不同的。当使用 CTE 生成数据时,FIRST_VALUE 会忽略 NULL。使用完全相同的 SQL,但将结果放在表变量或临时表中会导致 NULL 被考虑在内。
使用 CTE,SQL Server 结果在 FIRST_VALUE 确定中不包括 NULL:
WITH T AS
(
SELECT
T1.agroup,
T1.akey,
T2.aval
FROM
(
SELECT 1 agroup, 1 akey
UNION ALL SELECT 1, 2
UNION ALL SELECT 1, 3
) T1
LEFT JOIN
(
SELECT 1 akey, 10 aval
UNION ALL SELECT 3,30
) T2 ON T1.akey = T2.akey
)
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
T
但是使用表变量,它确实:
DECLARE @T TABLE (agroup INT,akey INT,aval INT)
INSERT INTO
@T
SELECT
T1.agroup,
T1.akey,
T2.aval
FROM
(
SELECT 1 agroup, 1 akey
UNION ALL SELECT 1, 2
UNION ALL SELECT 1, 3
) T1
LEFT JOIN
(
SELECT 1 akey, 10 aval
UNION ALL SELECT 3,30
) T2 ON T1.akey = T2.akey
SELECT
agroup,
aval,
FIRST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) fv,
LAST_VALUE(aval) OVER (PARTITION BY agroup ORDER BY aval ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) lv
FROM
@T
【问题讨论】:
-
SQLfiddle 同意你的看法。
-
看起来像一个错误,我看到一些关于
FIRST_VALUE()和LAST_VALUE()的 Connect 项目,但没有任何与ORDER BY和空值相关的内容。您使用的 SQL-Server 的确切版本是什么?您完成所有更新了吗? -
是的,Connect 站点。查看类似的Connect item, regarding LAST_VALUE() and CTEs
-
我看到你打开了一个关于这个的新连接项。 link for reference
-
我同意 ypercube 和 MartinSmith 的观点,这很可能是最罕见的询问,是产品中新发现的错误。出色的工作,+1。
标签: sql-server tsql sql-server-2012 aggregate-functions window-functions