SQL Server:具有空值的按变量列排序CASE语句

SQL Server:具有空值的按变量列排序CASE语句,sql,sql-server,sql-server-2008,tsql,sql-order-by,Sql,Sql Server,Sql Server 2008,Tsql,Sql Order By,我有一个查询,可以输出按各种列排序的结果,但我需要能够处理排序列中的空值。任何帮助都将不胜感激。以下是一个例子: Table [People] Columns [Name], [Birthday] (NULLABLE) 查询中,@Sort是一个整数,指定在哪个列上进行排序,@pageStart和@pageEnd是告诉查询返回哪个结果的整数。(我只返回选定的行,所以我使用嵌套在CTE中的[RowNum]列。还有其他处理正在进行,但为了简单起见,我将其删除。): 我知道可以使用以下语句处理空值:

我有一个查询,可以输出按各种列排序的结果,但我需要能够处理排序列中的空值。任何帮助都将不胜感激。以下是一个例子:

Table [People]
Columns [Name], [Birthday] (NULLABLE)
查询中,
@Sort
是一个整数,指定在哪个列上进行排序,
@pageStart
@pageEnd
是告诉查询返回哪个结果的整数。(我只返回选定的行,所以我使用嵌套在CTE中的
[RowNum]
列。还有其他处理正在进行,但为了简单起见,我将其删除。):

我知道可以使用以下语句处理空值:

ORDER BY (CASE WHEN [columnName] is NULL THEN 1 ELSE 0 END), [columnName]

我很难将其应用到我正在处理的查询中。。。任何帮助都将不胜感激!如果我能澄清什么,请告诉我。

看来你大部分时间都在那里。您可以使用
ISNULL()

您需要从相同的数据类型中选择相关的值,但是对于
@Sort=0
,您可以使用

CASE WHEN @Sort = 0 THEN ISNULL([Name], '') END, 
它看起来还可以将
CASE…WHEN…END
语句的序列压缩为一个类似

CASE @Sort
    WHEN 0 THEN ISNULL([Name], '')
    WHEN 2 THEN ISNULL([Birthday], 0)
...
...
END

您可以将排序参数与
CASE
表达式中的空检查组合在一起:

;with results as(
SELECT [Name], [Birthday], ROW_NUMBER() OVER  (ORDER BY 
       CASE WHEN @Sort = 0 AND [Name] IS NULL THEN 1 ELSE 0 END, [Name],
       CASE WHEN @Sort = 2 AND [Birthday] IS NULL THEN 1 ELSE 0 END, [Birthday],
       CASE WHEN @Sort = 1 AND [Name] IS NULL THEN 1 ELSE 0 END, [Name] DESC,
       CASE WHEN @Sort = 3 AND [Birthday] IS NULL THEN 1 ELSE 0 END, [Birthday] DESC)As RowNum
FROM [People]
)
SELECT [Name], [Birthday]
FROM results
WHERE RowNum BETWEEN @pageStart AND @pageEnd

您的查询在代码重用方面很好。不幸的是,它的优化能力也很差。(这是真的吗?)

对于这个单一查询,优化人员需要构建一个单一的执行计划。例如,它不能在排序的不同索引之间切换。相反,当参数发生变化时,它必须“手动”重新排序数据

这在分页中尤其重要。有了合适的索引,优化者可以使用范围搜索直接跳到所需的行。对于单个查询,其效果是实际处理整个表,适当地排序,然后跳转到适当的记录。(拥有一个适合所有参数的单一计划的结果)对于任何大量的数据,这都是一个非常大的开销


出于这个原因,使用动态SQL来实现这一点通常会更有效。这允许每个不同的订单有自己的执行计划。然后,每个计划案例都使用最适合这些需求的索引。

因此,我实际上使用动态SQL构建了这个(更复杂)查询的初始版本,但该查询的可维护性有点令人头痛,因此我随后切换到了这个…@brett-因此,我假设这是一个非常简化的版本?我同意动态sql感觉不雅观并且有可维护性开销,但是试图将所有这些压缩到一个查询中也会有很大的性能开销。这是一个可怕的权衡。[我还在为您查找一篇关于synamic serach的文章的链接。它与动态排序具有相同的特性。](链接由@MartinSmith在许多其他问题中提供)是的,实际的查询是一个丑陋的野兽。在这个查询中,我从一个临时表中提取,而不是从一个名为[Person]的表中提取。temp表是从一个SQL函数中构建出来的,随后用于计算和返回表,其中列出了结果集中的筛选数据……谢谢,这使它变得更干净,解决方案也可以工作great@Dems在性能方面有一些优点,但我想这实际上取决于您的数据集和服务器。毕竟,你的表现可能是可以接受的。
;with results as(
SELECT [Name], [Birthday], ROW_NUMBER() OVER  (ORDER BY 
       CASE WHEN @Sort = 0 AND [Name] IS NULL THEN 1 ELSE 0 END, [Name],
       CASE WHEN @Sort = 2 AND [Birthday] IS NULL THEN 1 ELSE 0 END, [Birthday],
       CASE WHEN @Sort = 1 AND [Name] IS NULL THEN 1 ELSE 0 END, [Name] DESC,
       CASE WHEN @Sort = 3 AND [Birthday] IS NULL THEN 1 ELSE 0 END, [Birthday] DESC)As RowNum
FROM [People]
)
SELECT [Name], [Birthday]
FROM results
WHERE RowNum BETWEEN @pageStart AND @pageEnd