强制连接的第一个表中的所有行

时间:2011-07-07 10:18:39

标签: mysql left-join

我有三张桌子,machines持有自动售货机,products持有所有可能的产品,machines_products是两者的交集,给出了每个产品线的库存数量在一台特定的机器上。如果产品没有存放在机器中,则第三个表中没有相应的行。

DESCRIBE machines_products;
+------------+------------------+------+-----+---------+-------+
| Field      | Type             | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+-------+
| machine_id | int(10) unsigned | NO   | PRI | 0       |       |
| product_id | int(10) unsigned | NO   | PRI | 0       |       |
| quantity   | int(10) unsigned | NO   |     | 0       |       |
+------------+------------------+------+-----+---------+-------+

每种产品都有一个类别(想想巧克力棒和饮料瓶),机器知道它可以销售什么类型的产品。我想要一个该类别的所有产品的结果表,以及特定机器的数量。我已经达到了这个目标:

SELECT products.*, SUM(quantity) qty
FROM products
LEFT JOIN machines_products USING (product_id)
WHERE machine_id=m AND category_id=c
GROUP BY product_id;

问题是这会过滤掉没有数量的所有行,而我想要的是左表中的所有行,如果没有相应的行,则qty列中的NULL / 0右手边。

顺便说一句:这不是一个功课问题!我今年30岁,坐在办公室里:o)

4 个答案:

答案 0 :(得分:2)

SELECT p.*
     , SUM(mp.quantity) AS qty
FROM products p
  LEFT JOIN machine_products mp
    ON mp.product_id = p.product_id
    AND mp.machine_id = m              --- this condition moved from WHERE to ON
WHERE p.category_id = c
GROUP BY p.product_id

答案 1 :(得分:1)

实际上我在发布后不久就找到了答案。诀窍是避免在machine_id子句中指定第三个表的主键(即product_idWHERE)中的任一列。通过在AND的{​​{1}}条件中使用JOIN,并在那里指定机器ID,我得到了我正在寻找的结果。

ON

Brendan建议的SELECT products.*, quantity FROM products LEFT JOIN machines_products ON products.product_id=machines_products.product_id AND machine_id=m WHERE category_id=c 函数在我的情况下不是必需的,因为我用PHP的COALESCE()函数检查了值,所以empty()没问题。

事实证明,在发布问题时,我一直没有需要NULL

答案 2 :(得分:0)

SELECT p.id, SUM(mp.quantity) AS qty 
FROM products p 
LEFT JOIN machines_products mp ON p.id=mp.product_id
WHERE mp.machine_id=m 
AND p.category_id=c 
GROUP BY p.id;

答案 3 :(得分:0)

如果等式中的单个值为NULL,则

SUM会返回NULL。首先COALESCE,然后是SUM

SELECT p.*, SUM(COALESCE(mp.quantity, 0)) AS qty
FROM products p
LEFT JOIN machine_products mp ON mp.product_id = p.id
WHERE mp.machine_id = m
AND p.category_id = c
GROUP BY p.id

我假设您在products中有一个名为id的列。重命名,如果它是不同的......