2016-05-23 9 views
0

私は以下の質問を単純化するために探しています。私は代替ソリューションの周りを頭で覆うことはできませんが、COALESCEクエリの簡略化

目的は、Col_CからCol_Dを取り出すことです。 Col_DがNULLを返す場合、Col_BからCol_Dを取得したいとします。 それがNULLを返す場合は、もう一度ラダーを上げ、Col_AからCol_Dを取得します。ただし、Col_BとCol_CがNULLの場合のみです。

テーブル

Table_A 
Col_A Col_B Col_C Col_X 
L000 3200 3220 0000 

Table_B 
Col_A Col_B Col_C Col_D 
L000 NULL NULL 3256 
L000 3200 NULL 6483 
L7213 
L000 3200 3220 NULL 
L000 3200 3230 9462 

クエリ

Col_D 
6483 

編集

DECLARE @X nvarchar(4) = '0000' 

DECLARE @A nvarchar(4), @B nvarchar(4), @C nvarchar(4) 
SELECT @A = Col_A, @B = Col_B, @C = Col_C FROM [Table_A] 
WHERE [Col_X] = @X 

SELECT COALESCE(
(SELECT [Col_D] FROM [Table_B] WHERE Col_C = @C AND Col_B = @B AND Col_A = @A), 
(SELECT [Col_D] FROM [Table_B] WHERE Col_C IS NULL AND Col_B = @B AND Col_A = @A), 
(SELECT [Col_D] FROM [Table_B] WHERE Col_C IS NULL AND Col_B IS NULL AND Col_A = @A) 
) AS Col_D 

予想される出力:追加Table_Aと予想される出力

+2

あなたが "Col_CからCol_Dを取得する" とはどういう意味ですか?これらはすべてTable_Bの右側の列ですか? – n8wrl

+0

期待する出力を含めることはできますか? –

+0

Table_B.Col_C = Table_A.Col_CのCol_D値を取得します。 @ n8wrlこれは役に立ちますか? –

答えて

1

SQL Serverは降順で並べ替えるときに最後にnullを並べ替えます。したがって、可能なすべての候補レコードを取得するだけです。つまり、col_dはnullでなくてはならず、col_aは一致していてはならず、col_bとcol_cは一致するか、またはnullでなければなりません。降順に並べ、一番上の行を取ります。

select col_d 
from table_b 
where col_d is not null 
and col_a = @a 
and (col_b = @b or col_b is null) 
and (col_c = @c or col_c is null) 
order by col_b desc, col_c desc; 

table_aを含む完全なクエリを:

select b.col_d 
from (select * from table_a where col_x = @x) a 
join table_b b on b.col_d is not null 
       and b.col_a = a.col_a 
       and (b.col_b = a.col_b or b.col_b is null) 
       and (b.col_c = a.col_c or b.col_c is null) 
order by b.col_b desc, b.col_c desc; 
+0

優れています。私が必要としていることを正確に実行します。特に、トップ1だけでなく、必要に応じてすべての値を取得する能力があります。ありがとう。 –

0

あなたが優先順位付け、1行をしたいです。したがって:

Select cold 
From t 
Where (cold = @a or colc is null) and 
     (Colb = @b or colb is null) 
Order by (case when colc is not null then 1 else 2 end), 
     (Case when colc is not null then 1 else 2 end) 
Fetch first 1 row only; 

データベースによっては、limitまたはtopを使用して1つの行を取得することができます。

+0

ここでロジックを理解していません。明確にしていただけますか? –

0

予想される出力を提供することで、意図を明確にする前にGordonが回答している可能性があります。私のクエリは、元のクエリと論理的に同じではないことに注意してください。最小のヌル値を持つ行が返されます(Col_A = @A)。たとえば、クエリではCol_CとCol_Aに値があり、Col_Bがnullの場合は結果が除外されますが、このクエリはnullになりません。また、行がない場合はCol_A = @A、NULL値の代わりに空の結果セットを返します。

新しいクエリが元のクエリと論理的に同一でなければならない場合は、読みやすくするために単純化できるかどうかはわかりませんが、パフォーマンスが向上する「複雑な」ソリューションがあるかもしれません。

SELECT TOP 1 Col_D 
FROM Table_B 
WHERE Col_A = @A 
ORDER BY CASE WHEN Col_B IS NOT NULL -- Sort null Col_B values to the bottom 
       THEN 1 
       ELSE 0 
     END, 
     CASE WHEN Col_C IS NOT NULL -- Sort null Col_C values to the bottom 
       THEN 1 
       ELSE 0 
     END, 
     CASE WHEN Col_D IS NOT NULL -- Sort null Col_D values to the bottom 
       THEN 1 
       ELSE 0 
     END