条件付き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
句で使用するなどの回避策を使用する必要がありますか?
これを試して
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 DateDropped = 0
AND (
(ISNULL(@JobsOnHold, 0) = 1 AND DateAppr >= 0)
OR
(ISNULL(@JobsOnHold, 0) != 1 AND DateAppr != 0)
)
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'
には特別なものはないことに注意してください。 0
と1
を使用することもできます。
通常、CASE式を、より使い慣れたブール式に書き換えることができます。これは、一般的にパフォーマンスの点で優れています。ただし、ロジックを変換するよりも、既存の式を使用する方が簡単な場合や保守しやすい場合があります。
クエリの問題は、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
)
多くの場合、条件付き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)