web-dev-qa-db-ja.com

SQL Serverの条件付きWHERE句

条件付きwhere句が必要なSQLクエリを作成しています。

次のようになります。

SELECT 
    DateAppr,
    TimeAppr,
    TAT,
    LaserLTR,
    Permit,
    LtrPrinter,
    JobName,
    JobNumber,
    JobDesc,
    ActQty,
    (ActQty-LtrPrinted) AS L,
    (ActQty-QtyInserted) AS M,
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N
FROM 
    [test].[dbo].[MM]
WHERE 
    DateDropped = 0
            --This is where i need the conditional clause 
    AND CASE
            WHEN @JobsOnHold = 1 THEN DateAppr >=  0
            ELSE  DateAppr != 0
        END

上記のクエリは機能していません。これは正しい構文ではありませんか、これを行う別の方法がありますか?

動的SQLを使用したくないので、他の方法がありますか、またはif elseを使用し、同じクエリを異なるwhere句で使用するなどの回避策を使用する必要がありますか?

59
user2721874

これを試して

SELECT 
    DateAppr,
    TimeAppr,
    TAT,
    LaserLTR,
    Permit,
    LtrPrinter,
    JobName,
    JobNumber,
    JobDesc,
    ActQty,
    (ActQty-LtrPrinted) AS L,
    (ActQty-QtyInserted) AS M,
    ((ActQty-LtrPrinted)-(ActQty-QtyInserted)) AS N
FROM 
    [test].[dbo].[MM]
WHERE 
    DateDropped = 0
    AND (
    (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
    OR 
    (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0)
    )

条件付きWHEREの詳細については、こちらをご覧ください

72
Mahesh

これを試してください-

WHERE DateDropped = 0
    AND (
        (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
        OR 
        (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0)
    )
25
Devart

WHERE句でCASE式を使用する方法の根本的な質問に答えるには:

最初に、CASE式の値にはブール値ではなく通常のデータ型の値が必要であることを覚えておいてください。 varchar、int、または何かでなければなりません。 SELECT Name, 76 = Age FROM [...]とは言えず、結果セットで'Frank', FALSEを取得することを期待できないのと同じ理由です。

さらに、WHERE句のすべての式にはブール値が必要です。それらはできない varcharまたはintの値を持ちます。 WHERE Name;WHERE 'Frank';とは言えません。比較演算子を使用してブール式にする必要があるため、WHERE Name = 'Frank';

つまり、CASE式はブール式の片側になければなりません。 CASE式を何かと比較する必要があります。それだけでは我慢できません!

ここに:

WHERE 
    DateDropped = 0
    AND CASE
            WHEN @JobsOnHold  = 1 AND DateAppr >= 0 THEN 'True'
            WHEN DateAppr != 0 THEN 'True'
            ELSE 'False'
        END = 'True'

最後に、左側のCASE式がブール式を'True' = 'True'または'False' = 'True'に変換する方法に注意してください。

'False''True'には特別なものはないことに注意してください。 01を使用することもできます。

通常、CASE式を、より使い慣れたブール式に書き換えることができます。これは、一般的にパフォーマンスの点で優れています。ただし、ロジックを変換するよりも、既存の式を使用する方が簡単な場合や保守しやすい場合があります。

11
Bacon Bits

クエリの問題は、CASE式では、THENおよびELSEの部分に、ブール値ではなく数値またはvarcharまたはその他のデータ型に評価される式が必要であるということです。値。

ブール論理(またはSQLが使用する3項論理)を使用して書き換えるだけです。

WHERE 
    DateDropped = 0
AND ( @JobsOnHold = 1 AND DateAppr >= 0 
   OR (@JobsOnHold <> 1 OR @JobsOnHold IS NULL) AND DateAppr <> 0
    )
7
ypercubeᵀᴹ

多くの場合、条件付きWHERE句を使用すると、非常に非効率的なクエリになります。これは、インデックスが使用される大規模なデータセットで顕著です。パラメーターのさまざまな値に対してクエリを最適化する最適な方法は、パラメーターの各値に対して異なる実行プランを作成することです。 OPTION (RECOMPILE)を使用してこれを実現できます。

この例ではおそらく大きな違いはありませんが、条件は2つのケースのいずれかでのみ使用されるべきであると言うと、大きな影響に気付くことができます。

この例では:

WHERE 
    DateDropped = 0
    AND (
    (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
    OR 
    (ISNULL(@JobsOnHold, 0) <> 1 AND DateAppr <> 0)
    )
OPTION (RECOMPILE)

ソース パラメータスニッフィング、埋め込み、およびRECOMPILEオプション

0
wezzix