MySQL - 使用 LEFT JOIN 会产生意想不到的结果
Posted
技术标签:
【中文标题】MySQL - 使用 LEFT JOIN 会产生意想不到的结果【英文标题】:MySQL - using LEFT JOIN gives unexpected results 【发布时间】:2017-03-19 02:42:59 【问题描述】:我有两张表orderedproducts 和productsinstocks。这是表结构:
orderedproducts 表:
+-----+---------+-----------+----------+--------------+
| id | orderid | productid | quantity | productgroup |
+-----+---------+-----------+----------+--------------+
| 117 | 1016186 | 265385 | 5 | Main |
| 118 | 1016186 | 407454 | 6 | Main |
| 119 | 1016186 | 975045 | 7 | Main |
| 120 | 1016186 | 975046 | 8 | Main |
+-----+---------+-----------+----------+--------------+
productsinstocks 表:
+----+---------+-----------+----------+
| id | stockid | productid | quantity |
+----+---------+-----------+----------+
| 20 | 903958 | 265385 | 200 |
| 21 | 903958 | 407454 | 205 |
| 22 | 903958 | 975045 | 210 |
+----+---------+-----------+----------+
如您所见,该库存在 orderedproducts 表中只有三种类型的产品。我想加入这些表以达到以下结果:
+---------+-----------+---------+-----------+------------+
| orderid | productid | stockid | order_qty | stock_qty |
+---------+-----------+---------+-----------+------------+
| 1016186 | 265385 | 903958 | 5 | 200 |
| 1016186 | 407454 | 903958 | 6 | 205 |
| 1016186 | 975045 | 903958 | 7 | 210 |
| 1016186 | 975046 | 903958 | 8 | NULL |
+---------+-----------+---------+-----------+------------+
我使用了以下查询:
SELECT op.orderid, op.productid, plo.stockid, op.quantity order_qty, plo.quantity stock_qty FROM orderedproducts op
LEFT JOIN productsinstocks plo
ON op.productid=plo.productid
WHERE op.orderid=1016186
AND plo.stockid=903958
但它给了我以下结果:
+---------+-----------+---------+-----------+------------+
| orderid | productid | stockid | order_qty | stock_qty |
+---------+-----------+---------+-----------+------------+
| 1016186 | 265385 | 903958 | 5 | 200 |
| 1016186 | 407454 | 903958 | 6 | 205 |
| 1016186 | 975045 | 903958 | 7 | 210 |
+---------+-----------+---------+-----------+------------+
我不知道我错过了什么。
【问题讨论】:
【参考方案1】:WHERE
子句中的以下条件是导致结果集中缺少记录的原因:
WHERE plo.stockid = 903958
orderedproducts
表中的缺失记录与productsinstocks
表中的任何记录都不匹配。因此,此记录的 stockid
值将是 NULL
,而您当前的 WHERE
条件会将其过滤掉。
相反,在WHERE
子句中添加检查OR plo.stockid IS NULL
以保留此记录:
SELECT op.orderid, op.productid, plo.stockid, op.quantity order_qty,
plo.quantity AS stock_qty
FROM orderedproducts op
LEFT JOIN productsinstocks plo
ON op.productid = plo.productid
WHERE op.orderid = 1016186 AND
(plo.stockid = 903958 OR plo.stockid IS NULL)
演示在这里:
SQLFiddle
【讨论】:
这仍然会生成相同的结果集。 您确定您复制了我的确切查询吗?它应该可以正常工作。 是的,我复制并粘贴了您发送的内容。 @MehdiB 该查询对我有用,至少使用您粘贴的确切数据。看看我在答案中包含的 Fiddle 演示。 你是对的。它在 sqlfiddle 上工作,但为什么它不适合我?我正在使用 wamp 和 mysql 5.6。奇怪!【参考方案2】:试试这个
SELECT op.orderid, op.productid, plo.stockid, op.quantity order_qty, plo.quantity stock_qty FROM orderedproducts op
LEFT JOIN productsinstocks plo
ON op.productid=plo.productid AND plo.stockid=903958
WHERE op.orderid=1016186
【讨论】:
【参考方案3】:首先,让我们看看 WHERE 和 ON 子句的作用
Where 子句决定为输出选择哪些行。
ON 子句决定为连接选择哪些行。
WHERE plo.stockid=903958
WHERE 子句的这一部分从输出中删除最后一行。
这里我们要在连接操作之前选择行。因此,让我们将条件从 WHERE 移动到 ON 子句。
SELECT op.orderid, op.productid, plo.stockid, op.quantity order_qty, plo.quantity stock_qty FROM orderedproducts op
LEFT JOIN productsinstocks plo
ON op.productid=plo.productid AND plo.stockid=903958 AND op.orderid=1016186
此外,您应该将 stockid 视为 NULL 而不是 903958 在最后一行。
【讨论】:
以上是关于MySQL - 使用 LEFT JOIN 会产生意想不到的结果的主要内容,如果未能解决你的问题,请参考以下文章
Mysql 连接(left join, right join, inner join ,full join)
MySQL 数据库中 left outer join 和 left join 啥区别?
mysql 从left join 到join到查询计划到联合索引的原理