4

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

Table [People]
Columns [Name], [Birthday] (NULLABLE)

Query where@Sort是一个 int 指定要对哪一列进行排序,@pageStartand@pageEnd是 int 告诉查询要返回哪些结果。(我只返回行的选择,所以我使用[RowNum]嵌套在 CTE 中的列。还有其他处理发生,但为简单起见,我将其删除。):

;with results as(
SELECT [Name], [Birthday], ROW_NUMBER() OVER  (ORDER BY 
         CASE WHEN @Sort = 0 THEN [Name] END,
         CASE WHEN @Sort = 2 THEN [Birthday] END,
         CASE WHEN @Sort = 1 THEN [Name] END DESC,
         CASE WHEN @Sort = 3 THEN [Birthday] END DESC) AS RowNum
FROM [People]
)
SELECT [Name], [Birthday]
FROM results
WHERE RowNum BETWEEN @pageStart AND @pageEnd
--ORDER RowNum
--The last order by doesn't seem to be needed

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

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

我很难将其应用于我正在使用的查询......任何帮助将不胜感激!让我知道我是否可以澄清任何事情。

4

3 回答 3

2

好像你大部分时间都在那里。而不是一个CASE...WHEN...END声明,你可以改为使用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
于 2012-05-03T12:36:08.177 回答
1

您可以将排序参数与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
于 2012-05-03T12:36:12.950 回答
0

您的查询在代码重用方面很好。不幸的是,它在可优化性方面也很差。 (这甚至是一个真实的词吗?)

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

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

出于这个原因,使用动态 SQL 来处理这个问题实际上通常会更高效。这允许每个不同的排序都有自己的执行计划。然后每个计划案例都使用最适合这些需求的索引。

于 2012-05-03T12:41:27.267 回答