包含union的where子句仅返回第一个查询

时间:2014-11-29 14:33:43

标签: mysql sql where

我根据来自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

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:1)

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

如果它发生,那么你可以使用不同的功能。

答案 2 :(得分:1)

目前,您的查询中有大量重复的代码,我在此重复更详细地展示并标记以表示重复:

(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'或其他),尽管另一个并不是必需的。它还有助于显示识别主键和外键的最小模式。您似乎有一组非常相互关联的表格。

您应该显示从查询中得到的输出和您期望的输出,并根据您的样本数据解释两者的不同之处。