首页 > 解决方案 > WHERE 之后的 CASE 语句那么几个值之一可以为 NULL?

问题描述

我有这样的选择:

SELECT 
 * 
FROM 
 Table Tb 
WHERE
 Tb.LastModificationDate BETWEEN @StartDate And @EndDate 
 AND Tb.var1 = @var1
 AND Tb.var2 = @var2

@var1 和 @var2 可能为空(或只有其中一个),所以现在我为每种情况选择了 3 个(真正的选择更复杂,所以我提供了简化的示例)我正在尝试合并它们使用 CASE 进行一次选择,但到目前为止还没有运气 - 因为如果其中一个变量不为空,则无法理解如何包含 AND 子句。我相信它应该是这样的:

 SELECT 
  * 
 FROM 
  Table Tb 
 WHERE
  Tb.LastModificationDate BETWEEN @StartDate And @EndDate 
  (CASE WHEN @var1 IS NOT NULL THEN (AND Tb.var1 = @var1)
        WHEN @var2 IS NOT NULL THEN (AND Tb.var2 = @var2)
  END);

有什么建议吗?

标签: mysqlsqlcase

解决方案


要使用该CASE语句,您需要AND从该部分中删除该子句THEN并将其移至外部CASE以便评估结果。这是因为CASE不能将条件附加到WHERE子句 ( THEN AND)。

SELECT * 
FROM Table Tb 
WHERE Tb.LastModificationDate BETWEEN @StartDate And @EndDate 
AND (CASE 
    WHEN @var1 IS NOT NULL THEN Tb.var1 = @var1
    WHEN @var2 IS NOT NULL THEN Tb.var2 = @var2
END);

但是,上述方法将仅限于CASE @var* IS NOT NULL评估为 true 的第一个 " "。因此,如果同时提供@var1and @var2,则 CASE 只会返回Tb.var1 = @var1不会比较Tb.var2 = @var2。要在两者和都是
时检索结果,需要将其添加到语句中。@var1@var2NULLELSE trueCASE

(CASE 
    WHEN @var1 IS NOT NULL THEN Tb.var1 = @var1
    WHEN @var2 IS NOT NULL THEN Tb.var2 = @var2
    ELSE true
END);

绕过第一种情况限制的另一种方法是通过使用将标准直接应用于WHERE子句AND (IS NULL OR ...)

这将允许标准在以下 4 个条件下匹配:

  1. 不检查是否@var1两者@var2都是NULL
  2. @var1如果提供 ( Tb.var1 = @var1)
  3. @var2如果提供 ( Tb.var2 = @var2)
  4. @var1@var2如果两者都提供( Tb.var1 = @var1 AND Tb.var2 = @var2)
SELECT * 
FROM Table Tb 
WHERE Tb.LastModificationDate BETWEEN @StartDate And @EndDate 
AND (@var1 IS NULL OR Tb.var1 = @var1)
AND (@var2 IS NULL OR Tb.var2 = @var2);

工作示例:DB-Fiddle


推荐阅读