我有一个查询可以吐出按各种列排序的结果,但我需要能够处理排序列中的空值。任何帮助将不胜感激。这是一个例子:
Table [People]
Columns [Name], [Birthday] (NULLABLE)
查询@Sort
是指定要排序的列的int,@pageStart
和@pageEnd
是告知查询返回哪些结果的查询。 (我只返回选择的行,所以我使用嵌套在CTE中的[RowNum]
列。还有其他处理发生,但我为了简单起见将其删除。):
;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]
我很难将其应用于我正在使用的查询...任何帮助将不胜感激!如果我能澄清任何事情,请告诉我。
答案 0 :(得分: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
答案 1 :(得分:1)
您可以将sort参数与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
答案 2 :(得分:0)
您的查询在代码重用方面表现良好。不幸的是,它在可优化性方面也很差。 (这甚至是一个真正的词?)
对于此单个查询,优化器需要构建单个执行计划。例如,它不能在排序的不同索引之间切换。相反,当参数发生变化时,它必须“手动”重新排序数据。
这在分页中尤为重要。使用合适的索引,优化器可以使用范围搜索直接跳转到您需要的行。在单个查询的情况下,效果将是实际处理整个表,适当排序,然后跳转到适当的记录。 (具有适合所有参数的单一计划的结果。)对于任何大量数据,这是 extermely 大开销。
出于这个原因,使用Dynamic SQL实现这一点通常要高效得多。这允许每个不同的排序具有它自己的执行计划。然后每个计划案例都使用最适合这些需求的指数。