首页 > 解决方案 > 为什么我的 WHERE 子句中的括号会弄乱 JOIN?(SQL)

问题描述

我正在使用 DVM v1.1.0:https ://www.ibm.com/docs/en/dvm/1.1.0?topic=reference-supported-sql-functions 。当我尝试在 UNION 的 WHERE 语句中使用括号,然后将它与另一个表连接时,它给了我以下错误:

在 FROM 列表中发现无效的关键字 LEFT

我有 2 个表需要 UNION(称为 U_1 和 U_2),然后是第三个表,我必须 LEFT OUTER JOIN(称为 J_1)。

U_1 和 U_2 有 2 列需要过滤:1 列具有 1 个所需值“G”(FILTER_1VAL),1 列具有 2 个所需值“1”或“2”(FILTER_2VAL)。

我使用此过滤器对 UNION U_1 和 U_2 进行了此 SQL 调用:

SELECT * 
FROM U_1 
WHERE FILTER_1VAL = 'G' AND (FILTER_2VAL = '1' OR FILTER_2VAL = '2')

UNION

SELECT * 
FROM U_2 
WHERE FILTER_1VAL = 'G' AND (FILTER_2VAL = '1' OR FILTER_2VAL = '2')

这将返回(如预期的那样)与这些过滤器匹配的 U_1 和 U_2 的每一列。

对于这些表的 UNION 上的 JOIN 子句,我还有一些框架语法:

SELECT * 
FROM
    (SELECT * FROM U_1
     UNION
     SELECT * FROM U_2) full_union
LEFT OUTER JOIN 
    J_1 joined ON full_union.field1 = joined.field1

这也可以按预期工作;在适用的情况下返回 U_1 和 U_2 以及来自 J_1 的数据。

然后,您可以在嵌套的 UNION 中添加一些简单的 WHERE 子句来进行一些数据过滤:

SELECT * 
FROM
    (SELECT * 
     FROM U_1 
     WHERE FILTER_1VAL = 'G' AND FILTER_2VAL = '1' OR FILTER_2VAL = '2'
     UNION
     SELECT * 
     FROM U_2 
     WHERE FILTER_1VAL = 'G' AND FILTER_2VAL = '1' OR FILTER_2VAL = '2') full_union
LEFT OUTER JOIN 
    J_1 joined ON full_union.field1 = joined.field1

这运行良好并按预期返回。

但是,当我在 WHERE 子句中添加括号以进行更复杂的过滤并确保它基于我想要的正确 AND/OR 逻辑进行过滤时,它无法运行查询:

SELECT *
FROM (
    SELECT *
    FROM U_1
    WHERE FILTER_1VAL = 'G'
      AND (
           FILTER_2VAL = '1'
        OR FILTER_2VAL = '2'
      )
    
    UNION
    SELECT *
    FROM U_2
    WHERE FILTER_1VAL = 'G'
      AND (
           FILTER_2VAL = '1' 
        OR FILTER_2VAL = '2'
      )
  ) full_union
  LEFT OUTER JOIN J_1 joined ON full_union.field1 = joined.field1

2021 年 7 月 28 日,13:20:33:643 - 执行语句时出错。
2021 年 7 月 28 日 13:20:33:643 - [DV][JDBC 驱动程序] 在 FROM 列表中找到无效的关键字 LEFT
2021 年 7 月 28 日 13:20:33:643 - 停止 SQL 执行(迭代时间 = 47 毫秒)。

确实,WHERE 子句中 () 的存在似乎是触发此错误发生的原因;为什么会这样?有什么办法可以避免这种情况,或者强制操作的逻辑顺序,这样我就可以在不使用括号的情况下实现我想要的过滤?

编辑 7/29:请参阅下面的 Power Mouse 评论。将查询更改为:

SELECT *
FROM (
    SELECT *
    FROM U_1
    WHERE FILTER_1VAL = 'G'
      AND (
           FILTER_2VAL = '1'
        OR FILTER_2VAL = '2'
      )
      AND 1=1
    
    UNION
    SELECT *
    FROM U_2
    WHERE FILTER_1VAL = 'G'
      AND (
           FILTER_2VAL = '1' 
        OR FILTER_2VAL = '2'
      )
      AND 1=1
  ) full_union
  LEFT OUTER JOIN J_1 joined ON full_union.field1 = joined.field1

删除了错误并返回了正确的结果。我最好的猜测是 DVM 中的 SQL 解析器存在问题。

标签: sql

解决方案


我怀疑 U_1、U_2 和 J_1 不是您的实际表名,并且您问题中的代码没有直接复制并粘贴到帖子中。您可能有不匹配的括号,但您可能正确键入了帖子的查询。

以可读且易于排除故障的方式编写 SQL。然后会更容易看到您在第二个 WHERE 子句末尾缺少右括号。(从技术上讲,就在子查询之后。)


推荐阅读