76

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句で使用するなどの回避策を使用する必要がありますか?

4

6 に答える 6

98

これを試して

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 の詳細については、こちらを参照してください。

于 2013-09-05T07:01:03.700 に答える
26

これを試してみてください -

WHERE DateDropped = 0
    AND (
        (ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0) 
        OR 
        (ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0)
    )
于 2013-09-05T06:29:09.670 に答える
13

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'andについて特別なことは何もないことに注意してください'True'0必要に応じてandも使用できます1

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

于 2015-09-02T14:01:00.653 に答える
7

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

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

WHERE 
    DateDropped = 0
AND ( @JobsOnHold = 1 AND DateAppr >= 0 
   OR (@JobsOnHold <> 1 OR @JobsOnHold IS NULL) AND DateAppr <> 0
    )
于 2013-09-05T06:28:51.153 に答える
3

多くの場合、条件付きの 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 オプション

于 2019-02-05T14:32:05.230 に答える
1

これは、2 つのパラメーターのいずれかがストアド プロシージャに渡される場所を考えるのが簡単に思えました。それはうまくいくようです:

SELECT * 
FROM x 
WHERE CONDITION1
AND ((@pol IS NOT NULL AND x.PolicyNo = @pol) OR (@st IS NOT NULL AND x.State = @st))
AND OTHERCONDITIONS
于 2020-11-02T14:55:55.743 に答える