我有三张桌子,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右手边。
答案 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_id
和WHERE
)中的任一列。通过在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)
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
的列。重命名,如果它是不同的......