簡體   English   中英

SQL Server窗口函數子句中的條件排序順序

[英]Conditional sort order in SQL Server windowed function clauses

所以,這不是你的平均'有條件排序'問題......我在這里有一個相當棘手的問題。 :-)我想允許我的存儲過程為結果提供條件排序順序。 通常,這可以通過以下方式完成:

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

我想圍繞實際的ASC / DESC做一個CASE聲明,但這不起作用。 上述方法工作的原因是,當@SortAscending不等於給定值時,SQL Server將CASE語句轉換為常量NULL 所以,如果@SortAscending為0,你實際上有:

ORDER BY
    NULL ASC,
    SortColumn DESC

然后,第一個排序表達式什么都不做。 這是有效的,因為在常規SELECT語句中,您可以在ORDER BY子句中使用常量。

麻煩的是,我在存儲過程中排序的時間是在包含窗口函數ROW_NUMBER()SELECT語句中。 因此,我想將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是無效的。

任何人都可以想到一種方法,我可以有條件地改變UNION ed SELECT的排序順序,並為這些排序結果的每一行分配行號嗎? 我知道我可以將整個查詢構造為字符串並將其作為完全動態的SQL執行,但如果可能的話,我寧願避免使用它。


更新:看起來問題不是由CASE語句本身引起的,而是由於我在CASE語句的條件子句中僅使用常量值。 我已經開始了這條奇怪的行為,一個新的問題在這里

如果將它們包裝在SELECT中,則可以使用常量,例如:

OVER( ORDER BY (SELECT NULL) )

所以在你的情況下你應該能夠做到:

SELECT
    ROW_NUMBER() OVER (
        ORDER BY
            (SELECT CASE WHEN @SortAscending=1 THEN rowValues.[SortColumn] END) ASC,
            (SELECT CASE WHEN @SortAscending=0 THEN rowValues.[SortColumn] END) DESC
    ) AS RowNumber, 

您可以在兩個方向上分配行號,並按外部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

SE Data的工作示例。

你可以

  • 在中間結果中添加Ascending和Descending列
  • 最后對其中一個進行排序。

SQL語句

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

如果你打算將這些行號用作其他條件邏輯的一部分,那么這樣的東西可能會起作用:

CASE WHEN @SortAscending=1 THEN COUNT(*) OVER() + 1 ELSE 0 END +
(CASE WHEN @SortAscending=1 THEN -1 ELSE 1 END *
    ROW_NUMBER() OVER (ORDER BY SortColumn DESC)) as RowNumber

這甚至可以擴展,這樣如果你使用PARTITION子句,只要兩個OVER()表達式都使用相同的PARTITION子句,它就會繼續工作。

您可以按order by使用窗口功能,而不僅僅是在選擇中。 窗口函數row_number,rank,dense_rank,都返回一個數字(bigint),您可以將其乘以負值以獲得反向...

SELECT *
INTO #ResultsBeforeSubset
FROM MyTable
ORDER BY
  (rank() over (order by SortColumn)) * case when @asc=1 then 1 else -1 end 
DECLARE @sign int = -1;
IF @SortAscending = 0 SET @sign = -1;

SELECT ROW_NUMBER() OVER (ORDER BY RowNumber) AS RN,
    *
INTO #ResultsBeforeSubset
FROM (
    SELECT
        @sign * ROW_NUMBER() OVER (ORDER BY rowValues.[SortColumn]) AS RowNumber,
        *
    FROM MyTable
) rowValuesWithRowNum
ORDER BY RN

--DECLARE @sign int = 1;
--IF @SortAscending = 0 SET @sign = -1;
--
--SELECT *
--INTO #ResultsBeforeSubset
--FROM (
--    SELECT
--        @sign * ROW_NUMBER() OVER (ORDER BY rowValues.[SortColumn] AS RowNumber,
--        *
--    FROM MyTable
--) rowValuesWithRowNum
--ORDER BY RowNumber;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM