![](/img/trans.png)
[英]Sql server - Windowed functions can only appear in the SELECT or ORDER BY clauses
[英]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的工作示例。
你可以
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.