一尘不染

SQL Server窗口函数子句中的条件排序顺序

sql

因此,这不是您的平均“条件排序依据”问题……我这里有一个非常棘手的问题。:-)我想允许我的存储过程为结果提供条件排序顺序。通常,可以通过以下方式完成此操作:

SELECT *
INTO #ResultsBeforeSubset
FROM
    MyTable
ORDER BY
    CASE WHEN @SortAscending=1 THEN 'SortColumn' END ASC,
    CASE WHEN @SortAscending=0 THEN 'SortColumn' END DESC

我想CASE围绕实际ASC/声明DESC,但这不起作用。上面的方法起作用的原因是因为,当@SortAscending不等于给定值时,SQL
Server会将CASE语句转换为常数NULL。因此,如果@SortAscending为0,则实际上有:

ORDER BY
    NULL ASC,
    SortColumn DESC

那么,第一个排序表达式什么也不做。之所以可行,是因为SELECT您可以在常规语句中在ORDER BY子句中使用常量。

麻烦的是,我在存储过程中进行排序的时间是在SELECT包含窗口函数的语句期间ROW_NUMBER()。因此,我想将该CASE语句放在其OVER子句中,如下所示:

SELECT *
INTO #ResultsBeforeSubset
FROM (
    SELECT
        ROW_NUMBER() OVER (
            ORDER BY
                CASE WHEN @SortAscending=1 THEN rowValues.[SortColumn] END ASC,
                CASE WHEN @SortAscending=0 THEN rowValues.[SortColumn] END DESC
        ) AS RowNumber,
        *
    FROM (
        -- UNIONed SELECTs returning rows go here...
    ) rowValues
) rowValuesWithRowNum

不幸的是,这会在您运行存储过程时导致以下错误:

Windowed functions do not support constants as ORDER BY clause expressions.

因为这是窗口函数的子句,所以将CASE语句转换为常量NULL是无效的。

谁能想到有条件地改变UNIONedSELECT的排序顺序,并为这些排序结果产生的每一行分配行号的方法?我知道我可以求助于将整个查询构造为字符串并将其作为完全动态的SQL执行,但是如果可能的话,我宁愿避免这样做。



阅读 134

收藏
2021-05-23

共1个答案

一尘不染

您可以在两个方向分配行号,然后在外部选择一个order by

select  *
from    (
        select  row_number() over (order by SortColumn) rn1
        ,       row_number() over (order by SortColumn) rn2
        ,       *
        from    @t
        ) as SubQueryAlias
order by
        case when @asc=1 then rn1 end
,       case when @asc=0 then rn2 end desc
2021-05-23