首页 > 解决方案 > SQL查询获取多个订单状态的产品

问题描述

我们有一个产品、订单、order_items、order_status 模式,如下所示。订单表状态字段,取值;ORDERED、RECEIVING、RECEIVED 和 CANCELED,如 order_status 表中所定义。

产品和订单的架构。

与此数据交互的 UI 确实有一个“产品视图”,每个产品都有行。当用户选择产品时,下方的另一个视图(订单中)列出了所选产品所在的订单。

用户应该能够根据产品订单状态过滤产品视图。特别是,一个按钮“On Order”应该过滤产品视图以仅显示在 In Orders 视图中有记录且状态为“ORDERED”的产品记录。

以下查询返回多个产品行,源于一个产品存在于多个订单中的事实。

SELECT products.*,        
orders.`id` AS orderID,
orders.`status`    
FROM products 
LEFT JOIN order_items
 ON products.`id` = order_items.`product_id`
JOIN orders
 ON orders.`id` = order_items.`order_id`;

上述查询的结果

我们希望上述结果集在订单状态上“合并”。也就是说,对于每个不同的订单状态,结果集应该只有一个产品记录。然后,我们可以在“状态”字段中过滤产品视图。

下图显示了基于上述结果我们想要的结果集。红色表示它应该是结果的一部分。

期望的结果

如上图所示;

如何做到这一点?

标签: mysqlsqljoinleft-joingreatest-n-per-group

解决方案


用于GROUP BY将多行折叠为一。用于MIN(o.id)在每个组中获取明确定义的订单 ID。

SELECT p.*, MIN(o.id) AS orderID, o.status
FROM products AS p
JOIN order_items AS oi ON oi.product_id = p.id
JOIN orders AS o ON o.id = oi.order_id
GROUP BY p.id, o.status

LEFT JOIN在这种情况下使用没有意义。您永远不想按来自LEFT JOIN表的列进行分组,因为所有不匹配的行都将被分组在一起。如果您要过滤订单状态,您显然只想要订单中的产品。


推荐阅读