SQL 查询以获取处于多个订单状态的产品

SQL query to get products in multiple order states

我们有一个产品、订单、order_items、order_status 架构,如下所示。 订单 table 的状态字段,取值;已订购、正在接收、已接收和已取消,如 order_status table.

中所定义

与此数据交互的 UI 确实有一个 'product view',每个产品都有行。作为用户 select 产品,下面的另一个视图(在订单中)列出了 selected 产品所在的订单。

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

的产品记录

以下查询 returns 多个产品行,源于一个产品存在于多个订单中。

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`;

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

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

如上图所示;

如何实现?

如果你是运行MySQL8.0,可以用row_number()进行过滤。我想你想要的逻辑是:

select *
from (
    select 
        p.*,        
        o.id as orderid,
        o.status    ,
        row_number() over(partition by p.id, o.status order by o.id) rn
    from products p
    inner join order_items oi on p.id = oi.product_id
    inner join orders o on o.id = oi.order_id
) t
where rn = 1

我认为混合 inner joinleft join 在这里没有意义。要么使用两个 inner joins(如上述查询),要么使用两个 left joins 如果您想保留没有任何订单的产品。

使用GROUP BY 将多行合并为一行。使用 MIN(o.id) 获取每个组中的 well-defined 订单 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 table 的列分组,因为所有不匹配的行都将分组在一起。如果您根据订单状态进行过滤,您显然只需要订单中的产品。