【问题标题】:where clause containing union returns the first query only包含 union 的 where 子句仅返回第一个查询
【发布时间】:2014-11-29 14:33:43
【问题描述】:

我正在根据 new_cards 表和 old_cards 表中的卡号从 2 个表中获取数据 "如果 card_code 包含'8',我想从这两个表中显示 card_code 和 card_status"

(SELECT * 
FROM bills INNER JOIN cats INNER JOIN suppliers
INNER JOIN new_cards
WHERE new_cards.`Card_Code` LIKE '%8%'
AND bills.`Sup_ID` = suppliers.`Sup_ID`
AND new_cards.`Sup_ID`  = suppliers.`Sup_ID`
AND cats.`Cat_ID` = bills.`Cat_ID`
AND new_cards.`Cat_ID` = cats.`Cat_ID`
AND new_cards.`Bill_ID` = bills.`Bill_ID`)
UNION
(SELECT * FROM bills INNER JOIN cats INNER JOIN suppliers
INNER JOIN sold_cards WHERE
sold_cards.`Card_Code` LIKE '%8%'
AND bills.`Sup_ID` = suppliers.`Sup_ID`
AND sold_cards.`Sup_ID`  = suppliers.`Sup_ID`
AND cats.`Cat_ID` = bills.`Cat_ID`
AND sold_cards.`Cat_ID` = cats.`Cat_ID`
AND sold_cards.`Bill_ID` = bills.`Bill_ID`)

但结果是第一张表中的card_coldes,它是new_cards

【问题讨论】:

  • 看起来您想要一个 UNION 语句,但不是很清楚。你能展示一个你希望输出看起来像什么的样本吗?
  • 代码已编辑,请查看

标签: mysql sql where


【解决方案1】:

你确定有匹配的吗?删除第二个查询并查看是否返回任何结果。如果组合行与所有表中的所有条件都不匹配,则不会出现。这意味着必须有行来连接 new_cards 和 solid 卡。您可能正在寻找 LEFT JOIN 而不是 INNER JOIN

由于您没有在 new_cards 条件中提及solid_cards,反之亦然,它还将尝试加入符合第二个条件的每一行,乘以 new_cards 中的每一行。小心这样的 OR 查询,它们的效率极低,尤其是在大型数据库上。

【讨论】:

  • 我想显示来自 2 个表 f card_code 的数据,例如 '%8%',但我得到了更多字段,正如您在所附照片中看到的那样。
  • 是的,因为您要连接 2 个具有相同字段的表,您可能希望使用 UNION 来代替
  • OK 现在可以工作了,但是当通过 bills.ID 添加订单时,在查询的最后一行添加订单时,查询返回错误
【解决方案2】:

提示:为避免查询结果中的任何重复,每行的所有记录不应具有不同的值。

如果发生这种情况,您可以使用 distinct 函数。

【讨论】:

    【解决方案3】:

    目前,您的查询中有大量重复的代码,我在此重复这些代码,布局更加系统,并标记为重复:

    (SELECT * 
       FROM bills INNER JOIN cats INNER JOIN suppliers  -- ER1A
      INNER JOIN new_cards
      WHERE new_cards.`Card_Code` LIKE '%8%'            -- NR1A
        AND bills.`Sup_ID` = suppliers.`Sup_ID`         -- ER2A
        AND new_cards.`Sup_ID`  = suppliers.`Sup_ID`    -- NR2A
        AND cats.`Cat_ID` = bills.`Cat_ID`              -- ER3A
        AND new_cards.`Cat_ID` = cats.`Cat_ID`          -- NR3A
        AND new_cards.`Bill_ID` = bills.`Bill_ID`)      -- NR4A
    UNION
    (SELECT *
       FROM bills INNER JOIN cats INNER JOIN suppliers  -- ER1B
      INNER JOIN sold_cards
      WHERE sold_cards.`Card_Code` LIKE '%8%'           -- NR1B
        AND bills.`Sup_ID` = suppliers.`Sup_ID`         -- ER2B
        AND sold_cards.`Sup_ID`  = suppliers.`Sup_ID`   -- NR2B
        AND cats.`Cat_ID` = bills.`Cat_ID`              -- ER3B
        AND sold_cards.`Cat_ID` = cats.`Cat_ID`         -- NR3B
        AND sold_cards.`Bill_ID` = bills.`Bill_ID`)     -- NR4B
    

    ERxx 标签表示“完全重复”,NRxx 标签表示“接近重复”。我会在最少的数据量上构建 UNION,并在连接中使用 ON 条件,如下所示:

    SELECT * 
      FROM bills
     INNER JOIN cats ON bills.`Cat_ID` = cats.`Cat_ID`
     INNER JOIN suppliers ON bills.`Sup_ID` = suppliers.`Sup_ID`
     INNER JOIN 
           (SELECT * FROM new_cards
            UNION
            SELECT * FROM sold_cards
           ) AS cards ON cards.`Bill_ID` = bills.`Bill_ID`
     WHERE cards.`Card_Code` LIKE '%8%'
       AND cards.`Sup_ID` = suppliers.`Sup_ID`
       AND cards.`Cat_ID` = cats.`Cat_ID`
    

    WHERE 子句中的最后两个条件也是连接条件;可以将它们上移到 ON 子句中。但是,它们也应该是多余的——或者,如果它们不是多余的,它们很可能是您遇到问题的原因。

    这种重新表述的一个优点是,您可以通过简单地执行 UNION 子查询来演示它返回的内容。您可能更愿意将 Card_Code 上的过滤器放入 UNION;这样,您会看到(可能)更少的数据行。这可以永久完成;您可能最终在最外层的查询中没有 WHERE 子句。

    您还应该通过单独运行 UNION 的后半部分来测试您的原始查询,以查看它返回的内容。如果按照您的建议,它什么都不返回,那么您可以单独调试查询的后半部分。例如,问你一个问题:新卡有有效的账单代码吗?

    如果没有表的(最少)样本数据,就不可能再做任何事情了——比如new_cardssold_cards 各有 3 或 4 行(每行中的一行与 Card_Code 上的过滤条件不匹配),然后是 billscatssuppliers 表中必要的支持行(其中任何一个都不应超过 8 行)。

    您应该只在每个表中显示最少的必要列,再加上最多一个额外的列。例如,bills 具有列 Sup_IDBill_ID;您应该显示这些值,也许还有另一个('Bill_Name' 或其他),尽管另一个并不是真正必要的。它还有助于显示标识主键和外键的最小模式。您似乎有一组非常相互关联的表格。

    您应该显示您从查询中获得的输出和您期望的输出,并根据您的示例数据解释为什么两者不同。

    【讨论】:

      猜你喜欢
      • 2015-10-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多