是否可以对计算列进行ORDER BY而不将其包含在结果集中?

时间:2015-10-23 14:38:44

标签: sql sql-server

我有这个问题:

SELECT Column1, Column2, Column3, /* computed column */ AS SortColumn
FROM Table1
ORDER BY SortColumn

SortColumn没有其他用途来定义排序结果集的顺序。因此,我想在结果集中省略它以减少发送到客户端的数据的大小。以下失败......

SELECT Column1, Column2, Column3
FROM (
    SELECT Column1, Column2, Column3, /* computed column */ AS SortColumn
    FROM Table1
    ORDER BY SortColumn
) AS SortedTable1

...因为:

  

Msg 1033,Level 15,State 1

     

ORDER BY子句在视图,内联函数,派生表,子查询和公用表表达式中无效,除非还指定了TOP或FOR XML。

所以有这个hacky解决方案:

SELECT Column1, Column2, Column3
FROM (
    SELECT TOP /* very high number */ Column1, Column2, Column3, /* computed column */ AS SortColumn
    FROM Table1
    ORDER BY SortColumn
) AS SortedTable1

是否有一个我不知道的清洁解决方案,因为这听起来不是一种罕见的情况?

修改 已经给出的解决方案对我提到的查询确实很好。不幸的是,我遗漏了一个重要的细节:(已经存在的)查询包含两个SELECT,其间有一个UNION,这几乎改变了这个问题(再次简化,希望不会太简化) :

SELECT Column1, Column2, Column3
FROM Table1
UNION ALL
SELECT Column1, Column2, Column3
FROM Table1
ORDER BY /* computed column */
  

Msg 104,Level 16,State 1

     

如果语句包含UNION,INTERSECT或EXCEPT运算符,则ORDER BY项必须出现在选择列表中。

因此,此错误消息清楚地表明我必须将计算列放在两个选择列表中。因此,正如答案中所指出的那样,我们再次使用子查询解决方案,该解决方案无法可靠地工作。

6 个答案:

答案 0 :(得分:4)

您不需要在select语句中使用计算列来按顺序使用它

WITH src AS (
    SELECT Column1, Column2, Column3, ColumnNeededForOrderBy
    FROM Table1

    UNION ALL

    SELECT Column1, Column2, Column3, ColumnNeededForOrderBy
    FROM Table2
)
SELECT Column1, Column2, Column3
FROM src
ORDER BY /* computed column */

如果你需要使用UNION,那么在cte中执行UNION,在select中执行order by,确保包含在CTE中进行计算所需的所有列

print ""
print "               WAGE CALCULATOR TOOL   -    By Joel"
print""
print " Please enter details: "
name = raw_input("  Employee Name: ")
hrs = float(raw_input("  Hours Per Week: "))
rate = float(raw_input("  Hourly Rate: "))
pay = hrs * rate
print ""
print "",name,":","Wage amount: "
print " ",pay,"Per week"
week = pay * 4
print " ",week,"Every 4 weeks"
print""

done = raw_input("Restart? y/n: )

答案 1 :(得分:2)

如果出于某种原因,在ORDER BY中进行计算是不切实际的,那么你可以做一些与你的尝试非常相似的事情:

SELECT Column1, Column2, Column3
FROM (
    SELECT Column1, Column2, Column3, /* computed column */ AS SortColumn
    FROM Table1
) AS SortedTable1
ORDER BY SortColumn

请注意,此处更改的是ORDER BY应用于外部查询。引用ORDER BY中未出现在SELECT子句中的列是完全有效的。

答案 2 :(得分:1)

只需将表达式放在SELECT Column1, Column2, Column3, FROM Table1 ORDER BY <computed column>

ddplay

答案 3 :(得分:1)

这是禁止的原因是外部选择的顺序与内部选择的顺序无关 - 而不是通过合同。因此,如果您使用order by而没有top条款,那么您显然是犯了错误。通过使用top的方式,您只需隐藏错误,但仍然有同样的错误。

你的hack只能运行,因为引擎碰巧保留了命令 - 但这不是给定的,并且没有办法强制执行(除了在外部查询中使用order by)。例如,不同的索引使用或并行执行可能会扰乱您的数据。

所以不,没有其他方法 - 您需要在外部查询中order by,这需要您在子查询中输出要排序的列。除非你使用*,否则它不会有任何区别 - 你不需要在外部选择中选择它,只需选择内部选择。并且只有外部选择被发送到客户端:)

答案 4 :(得分:1)

ORDER BY的唯一位置是最外层的陈述。

当然也有例外情况:例如,如果您需要TOP记录过滤列表(例如,给定日期的最后一个有效值)。但在这些情况下,您必须ORDER BYTOP合并。

只有最外面的ORDER BY才会对您获得的列表进行排序。

答案 5 :(得分:1)

编辑后看起来就像你需要的那样

SELECT Column1, Column2, Column3
FROM
    ( 
    SELECT Column1, Column2, Column3
    FROM Table1
    UNION ALL
    SELECT Column1, Column2, Column3
    FROM Table1
    )
ORDER BY /* computed column */