【问题标题】:SQL: Ignore Condition in WHERE clauseSQL:忽略 WHERE 子句中的条件
【发布时间】:2020-01-28 00:26:01
【问题描述】:

如果 WHERE 子句的计算结果为 NULL,我对如何排除其中一个条件感到困惑

SELECT TB1.COL3 
FROM TB1, TB2
WHERE TB1.COL1 = TB2.Col1
AND TB2.COL1 = '12345'
AND (TB2.COL3 = (SELECT MIN(TB3.COL4)
FROM TB3
WHERE COL1 = TB2.COL1
AND COL2 in ('A', 'B') 
AND COL4 IN (SELECT COL3 FROM TB4 
WHERE COL1 = TB4.COL1))) 
AND ROWNUM = 1;

如果以下条件 SELECT MIN(TB3.COL4) FROM TB3 的计算结果为除 NULL 之外的某个值,我如何修改上述查询以忽略“AND 条件 TB2.COL3”。如果为 NULL,则上述查询应按如下方式执行:

SELECT TB1.COL3 
FROM TB1, TB2
WHERE TB1.COL1 = TB2.Col1
AND TB2.COL1 = '12345'
AND ROWNUM = 1;

【问题讨论】:

  • 查询很混乱。在 SELECT COL3 FROM TB2 WHERE COL1 = TB2.COL1 中,您缺少一个限定符。它被评估为SELECT COL3 FROM TB2 WHERE TB2.COL1 = TB2.COL1,因为 TB2 是您在子查询中使用的表。由于 TB2.COL1 = TB2.COL1` 始终为真,但 null 除外,因此您最终会得到 SELECT COL3 FROM TB2 WHERE TB2.COL1 IS NOT NULL。这是故意的吗?
  • 附带说明:逗号分隔的连接在 1992 年的 SQL 中变得多余。请使用显式连接 (FROM TB1 INNER JOIN TB2 ON ...)。然后,当查询全部为大写时,就很难阅读。要么将关键字保留为大写,要么将其全部小写。然后,由于缺少缩进,您的查询不是很可读。第一个子查询在哪里开始和结束,第二个在哪里?最后:一定要加入TB2吗?你没有从中选择,所以我宁愿期待INEXISTS。使用连接,您可能会冒得到重复结果行的风险。
  • @ThorstenKettner 我已经修改了将 TB2 替换为 TB4 的 SQL 以防止混淆。

标签: sql oracle


【解决方案1】:

我认为你可以通过合并来实现这一点:

SELECT TB1.COL3 
FROM TB1, TB2
WHERE TB1.COL1 = TB2.Col1
AND TB2.COL1 = '12345'
AND (TB2.COL3 = COALESCE((SELECT MIN(TB3.COL4)
FROM TB3
WHERE COL1 = TB2.COL1
AND COL2 in ('A', 'B') 
AND COL4 IN (SELECT COL3 FROM TB2 
WHERE COL1 = TB2.COL1)), TB2.COL3)) 
AND ROWNUM = 1;

这里我们只是将 SELECT 语句包装在 COALESCE 中,如果它返回 null,则将获取第二个参数的值,而不是我们正在比较的同一列。由于TB2.COL3 = TB2.COL3 显然是TRUE,那么这个过滤器不会对结果集产生任何影响。

此外,通常建议您停止在 FROM 子句中使用逗号并使用正确的 JOIN 语法。它已经存在了 2 多年了:

SELECT
    TB1.COL3
FROM
    TB1
    INNER JOIN TB2
        ON TB1.COL1 = TB2.Col1
WHERE
    TB2.COL1 = '12345'
    AND
    (
        TB2.COL3 = COALESCE
        (
            (
                SELECT
                    MIN(TB3.COL4)
                FROM
                    TB3
                WHERE
                    COL1 = TB2.COL1
                    AND COL2 in ('A', 'B')
                    AND COL4 IN
                    (
                        SELECT
                            COL3
                        FROM
                            TB2
                        WHERE
                            COL1 = TB2.COL1
                    )
            ),
            TB2.COL3
        )
    )
    AND ROWNUM = 1;

【讨论】:

  • 感谢您的回复和解释!我没有考虑应用 COALESCE。我也同意在 from 子句中使用 JOINS。
  • 如果 TB2.COL3 为 NULL,则此方案不适用于所有情况。然后条件评估为 False。我们怎样才能避免这种情况?
  • 另一个coalesce() 可以解决问题:COALESCE(TB2.Col3, 1) = COALESCE(<select statement>, TB2.COL3, 1) 这样它将继续运行,直到在COALESCES() 中都达到1 并返回TRUE。可以选择将OR TB2.COL3 IS NULL 扔进这个位可能会奏效。 50/50 哪个更快。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-31
  • 1970-01-01
相关资源
最近更新 更多