所以,这不是你的平均'有条件排序'问题......我这里有一个相当棘手的问题。 :-)我想允许我的存储过程为结果提供条件排序顺序。通常,这可以通过以下方式完成:
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
的{{1}}语句中。因此,我想将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
ed UNION
的排序顺序,并为这些排序结果的每一行分配行号吗?我知道我可以将整个查询构造为字符串并将其作为完全动态的SQL执行,但如果可能的话,我宁愿避免使用它。
更新:看起来这个问题不是由SELECT
语句本身造成的,而是因为我只使用了常量值CASE
语句的条件子句。我已经开始提出一个关于这种奇怪行为的新问题here。
答案 0 :(得分:3)
如果将它们包装在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,
答案 1 :(得分: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
SE Data的工作示例。
答案 2 :(得分:1)
你可以
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
答案 3 :(得分:1)
如果您打算将这些行号用作其他条件逻辑的一部分,那么这样的事情可能会起作用:
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
子句,它就会继续有效。
答案 4 :(得分:0)
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;
答案 5 :(得分:0)
您可以在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