2012-05-03 7 views
4

結果をさまざまな列で並べ替えることができるクエリがありますが、ソート列にNULL値を処理できる必要があります。どんな助けでも大歓迎です。 @Sortは上の並べ替え、および@pageStart@pageEndを返すように結果のクエリを語ったintあるために列int型指定されSQL Server:ORDER BY可変列NULL値のCASE文

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

クエリ:ここでは一例です。 (私は、行の選択のみを返していますので、私は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] 

:ヌルのようなステートメントで処理することができます!私が何かを明確にすることができたら教えてください。

答えて

2

あなたはほとんどそこにいるようです。代わりに、あなたが代わりにあなたが同じデータ型から関連する値を選択する必要がありますが、例えば@Sort = 0のためにあなたがあなたを凝縮できたようですが、また見え

CASE WHEN @Sort = 0 THEN ISNULL([Name], '') END, 

を使用することができますISNULL()

を使用することができCASE...WHEN...END文のあなたはにnullをチェックしてsortパラメータを組み合わせることができ

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

ありがとう、それは多くのクリーナーになり、ソリューションは素晴らしい動作します – Brett

+0

@Demsはパフォーマンスに関していくつかの良い点を作りますが、私は本当にあなたのデータセットとサーバーに依存していると思います。 Afterallのパフォーマンスはあなたにとって受け入れられるかもしれません。 – Goody

1

のような1以上にCASE...WHEN...END一連の文0式:

;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 
0

あなたのクエリはコードの再利用の面で優れています。残念ながら、それは最適化の面でも貧弱です。 は(あっても、実際の言葉ですか?)この単一のクエリのために

は、オプティマイザは単一実行計画を構築する必要があります。例えば、順序付けのために異なるインデックス間を切り替えることはできません。代わりに、パラメータが変更されたときにデータを「手動で」並べ替える必要があります。

これは特にページングに関係します。適切な索引を使用すると、オプティマイザはレンジ・シークを使用して必要な行にまっすぐジャンプできます。単一のクエリの場合、実際にはテーブル全体を適切に処理し、適切なレコードにジャンプすることになります。 (すべてのパラメータに合わせて単一の計画を作成した結果)相当な量のデータの場合は、が外部では大きいオーバーヘッドです。

このため、実際には動的SQLを使用してこれにアプローチする方がずっと効果的です。これにより、それぞれの異なる順序付けに独自の実行計画を持たせることができます。そして、それぞれのプランケースは、それらのニーズに最も適切なインデックスを使用します。

+0

私は実際に動的SQLを使用してこの(より複雑な)クエリの初期バージョンを構築しましたが、そのクエリの保守性は少し頭痛でしたので、その後これに切り替えました... – Brett

+1

@brett - 私は仮定したがって、これははるかに単純化されたバージョンですか?私は、動的SQLは控えめで、保守性のオーバーヘッドがあることに同意しますが、このすべてを単一のクエリに絞り込もうとすると、重大なパフォーマンスオーバーヘッドが発生する可能性があります。それは恐ろしいトレードオフです。 * [私はまた、あなたのために力強い救助に関する記事へのリンクを探しています。 ] * – MatBailie

+1

http://www.sommarskog.se/dyn-search.html *(多くの他の質問で@MartinSmithのリンクの礼儀)* – MatBailie