【问题标题】:ORDER BY ROW_NUMBER按 ROW_NUMBER 排序
【发布时间】:2011-08-01 17:03:05
【问题描述】:

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() 函数一起使用。谁能给我解释一下?

【问题讨论】:

  • 如果您将 AVG(mark) 添加到 SELECT 子句(以及此结果),也许会有所帮助。那时可能很明显。 (我敢打赌,Pete 和 John 的平均值是一样的。)
  • 源数据类似于 (Pete, 10), (Pete, 15), (Pete, 10), (John, 15), (John, 20)。没关系
  • 不确定您要在这里做什么:窗口函数没有意义
  • 是的,没有它们也可以完成,线索是了解它们是如何工作的。

标签: sql tsql


【解决方案1】:

当然可以按 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

将查询更改为 number 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 名
【解决方案2】:

您不能直接按 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 name ORDER BY name 是没有意义的。每个分区都有随机顺序,因为排序分区

我怀疑你想要这样的东西,其中 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 这是有道理的:我知道您的问题是关于 如何 它的工作原理的抽象问题,这个问题不清楚。如果您用简单的英语描述您想要的内容并带有示例输入和输出,那会更有意义

【讨论】:

  • 某个好人以我的查询 data.stackexchange.com/stackoverflow/q/107997 为例。他只是添加了几个字段,但是可以编辑查询。那里也没有任何错误
  • 请注意,“您不能直接按 ROW_NUMBER 排序”语句并不完全正确。您可以按列别名排序,而无需使用子查询。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
  • 2021-04-06
  • 1970-01-01
  • 2022-07-06
相关资源
最近更新 更多