代码之家  ›  专栏  ›  技术社区  ›  Amirshk

SQL:标记条件匹配的位置

  •  2
  • Amirshk  · 技术社区  · 14 年前

    这是一个理论上的问题,我想知道是否有一个很好的方法来找出语句在哪里匹配的条件。

    假设我有这样的问题:

    SELECT * FROM table WHERE
        COND1 OR
        (COND2 AND COND3) OR
        COND4
    

    是否有任何方法可以知道哪些条件使给定的行匹配(或取消匹配)?


    我想到的一个解决方案是向select中添加case子句,然后重新运行该行的所有where条件:

    SELECT *, which_cond = CASE .... END CASE ...
    
    2 回复  |  直到 14 年前
        1
  •  3
  •   Felix Kling    14 年前

    CASE 是一种可能性。但写得更短 IF() (至少使用MySQL):

    SELECT *, IF(COND2, 1, 0) AS cond2, IF(COND3, 1, 0) as cond3 ... 
    

    cond* 如果其值为 1 .

    当然,检查 COND1 是否匹配。对于你得到的所有结果, COND1 是真的。所以 IF(COND1, 1, 0) 会一直回来的 (在您的示例中)。

    更新 :
    我发现,至少对于MySQL来说,如果您只想得到 0 结果是:

    SELECT *, COND2 AS cond2, COND3 as cond3 ...
    

    至于马克的答案,如果你使用 HAVING 而不是 WHERE ( 作为对别名的访问):

    SELECT *, COND2 AS cond2, COND3 as cond3
    FROM table
    HAVING COND1 AND (cond2 OR cond3)
    

    (注:大写表示实际条件表达式,小写为别名)

    更新2:

    嗯,变化不大:你只需要检查通过 OR 在您的更新版本中,检查 COND2 是真是假。如果是这样,那么 COND3 也是真的,反之亦然。

    SELECT *, COND1 AS cond1, COND2 as cond2, COND4 as cond4
    FROM table
    HAVING cond1 OR (cond2 AND COND3) OR cond4
    

    我认为这一点很清楚。

        2
  •  1
  •   Mark Byers    14 年前

    您的方法可以工作,但它要求您将所有条件键入两次,如果这些条件是复杂的表达式,则可能会很烦人。当需要更改条件而忘记更新这两个地方时,代码的重复也会导致错误。我建议使用子选择来评估条件,而不是从那里使用别名:

    SELECT *,
           CASE WHEN Cond1 AND Cond2 THEN 'Foo'
                ELSE 'Bar'
           END AS WhichCondition
    FROM (SELECT *,
               (...SQL FOR COND1...) AS Cond1,
               (...SQL FOR COND2...) AS Cond2,
               (...SQL FOR COND3...) AS Cond3
               FROM table) AS T1
    WHERE Cond1 AND (Cond2 OR Cond3)
    

    在SQL Server和Oracle上,可以使用CTE而不是子查询。我没有这样做,因为你也使用了mysql标签。