有一个简单的代码。我一直以为ROW_NUMBER和CROSS APPLY子句中的一个都应该生成相同的输出(在我的例子中我除了rn = crn)。你能解释一下为什么不是这样吗?
CREATE TABLE #tmp ( id INT, name VARCHAR(200) );
INSERT INTO #tmp
VALUES ( 1, 'a' ),
( 2, 'a' ),
( 3, 'a' ),
( 4, 'b' ),
( 5, 'b' ),
( 6, 'c' ),
( 7, 'a' );
SELECT name,
ROW_NUMBER() OVER ( PARTITION BY name ORDER BY id ) AS rn,
a.crn
FROM #tmp
CROSS APPLY (
SELECT ROW_NUMBER() OVER ( PARTITION BY name ORDER BY id ) AS crn
) a;
输出:
name rn crn
a 1 1
a 2 1
a 3 1
a 4 1
b 1 1
b 2 1
c 1 1
答案 0 :(得分:4)
CROSS APPLY中的查询应用于#tmp
中的每一行。查询选择它应用的那一行,即那一行的行号,当然是一行。
微软Technet上的this article可能会让您更深入地了解CROSS APPLY的工作原理。摘录突出了我在前一段中所写的内容:
APPLY运算符允许您为查询的外表表达式返回的每一行调用表值函数。表值函数用作右输入和外表表达式充当左输入。 从左输入中为每一行评估正确的输入,并将生成的行合并为最终输出。 APPLY运算符生成的列列表是左输入中的列集,后跟右输入返回的列列表。
答案 1 :(得分:3)
请注意,APPLY
正在使用主查询中的字段作为参数。
SELECT ROW_NUMBER() OVER ( PARTITION BY name ORDER BY id ) AS crn
上述查询没有FROM
子句。所以它将name
和id
视为文字。为了说明,对于#tmp
的第一行,CROSS APPLY
的结果查询是:
SELECT ROW_NUMBER() OVER ( PARTITION BY (SELECT 'a') ORDER BY (SELECT 1)) AS crn
返回:
crn
--------------------
1
这是每行CROSS APPLY
的结果。
为了达到预期的效果:
SELECT
t.name,
ROW_NUMBER() OVER ( PARTITION BY t.name ORDER BY t.id ) AS rn,
a.crn
FROM #tmp t
CROSS APPLY(
SELECT id, ROW_NUMBER() OVER (PARTITION BY name ORDER BY id ) AS crn
FROM #tmp
) a
WHERE t.id = a.id