按行ROW_NUMBER

时间:2011-07-31 15:49:47

标签: sql tsql

UPD:感谢所有人,主题关闭,睡了之后我明白了一切=)

我在理解OVER子句和ROW_NUMBER函数时遇到问题。简单的表 - 名称和标记。我想计算每个名字的平均分数。

SELECT top 1 with ties name,  ROW_NUMBER() over (PARTITION BY name ORDER BY name) as number
FROM table 
ORDER BY AVG(mark) OVER(PARTITION BY name)

它会显示这样的内容,我理解为什么 - 这就是ROW_NUMBER()所做的

name|number
Pete 1
Pete 2

但如果我写

SELECT top 1 with ties name,  ROW_NUMBER() over (PARTITION BY name ORDER BY name) as number
FROM table 
ORDER BY AVG(mark) OVER(PARTITION BY name), number

它会显示

name|number
Pete 1

这次我不明白ORDER BY如何与ROW_NUMBER()函数一起使用。有人可以向我解释一下吗?

2 个答案:

答案 0 :(得分:7)

当然可以通过ROW_NUMBER列进行排序,因为SELECT子句是在ORDER BY子句之前计算的。您可以按任何列别名进行排序。这就是没有抛出错误消息的原因(因为它是有效的)。

SELECT name,  ROW_NUMBER() over (PARTITION BY name ORDER BY name) as number
FROM @table 
ORDER BY number

评估到

name       number
---------- --------------------
John       1
pete       1
pete       2
John       2
pete       3

OP的第二个row_number示例不正确。

SELECT AVG(mark) OVER(PARTITION BY name), name,  ROW_NUMBER() over (PARTITION BY name ORDER BY name) as number
FROM @table 
ORDER BY AVG(mark) OVER(PARTITION BY name), number

按预期返回,因为AVG是第一个排序后跟数字的排序列。

            name       number
----------- ---------- --------------------
11          pete       1
11          pete       2
11          pete       3
17          John       1
17          John       2

将查询更改为编号DESC ,并且pete仍然是第一个,但行号是降序。

            name       number
----------- ---------- --------------------
11          pete       3
11          pete       2
11          pete       1
17          John       2
17          John       1

SQL操作顺序

FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause

答案 1 :(得分:3)

你不能直接通过ROW_NUMBER订购:我不知道为什么你没有在这种情况下得到错误,但通常你会这样做。因此使用派生表或CTE

SELECT
    name, number
FROM
    (
    SELECT
       name,
       ROW_NUMBER() OVER (PARTITION BY name ORDER BY name) as number,
       AVG(mark) OVER (PARTITION BY name) AS nameavg
    FROM table
    ) foo
ORDER BY
   nameavg, number

然而,PARTITION BY名称ORDER BY名称毫无意义。每个分区都有随机顺序,因为排序分区

我怀疑你想要这样的东西,其中ROW_NUMBER基于AVG

SELECT
    name, number
FROM
    (
    SELECT
       name,
       ROW_NUMBER() OVER (PARTITION BY name ORDER BY nameavg) AS number
    FROM
        (
        SELECT
           name,
           AVG(mark) OVER (PARTITION BY name) AS nameavg
        FROM table
        ) foo
    ) bar
ORDER BY
    number

传统上更为传统(但名称因平均而崩溃)

SELECT
    name, number
FROM
    (
    SELECT
       name,
       ROW_NUMBER() OVER (PARTITION BY name ORDER BY nameavg) AS number
    FROM
        (
        SELECT
           name,
           AVG(mark) AS nameavg
        FROM
           table
        GROUP BY
           name
        ) foo
    ) bar
ORDER BY
    number

可能将派生的foo和bar折叠成一个

ROW_NUMBER() OVER (PARTITION BY name ORDER BY AVG(mark))

none 这是有道理的:我明白你的问题是抽象的如何它的作用有点不清楚问题。如果用简单的英语和样本输入和输出描述你想要的东西会更有意义