我们有一个产品,订单,order_items,order_status模式,如下所示。 订单表状态字段,取值;按照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`;
我们希望上述结果在订单状态上设置为“ coalesce”。也就是说,对于每个不同的订单状态,结果集应仅具有一个产品记录。然后,我们可以在“状态”字段中过滤产品视图。
下面的图像根据上述结果显示了我们想要的结果集。红色表示不不应包含在结果中。
如上图所示;
如何实现?
答案 0 :(得分:1)
如果运行的是MySQL 8.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 join
和left join
在这里是没有道理的。要么使用两个inner join
(如上面的查询中所述),要么使用两个left join
(如果要保留没有任何订单的产品)。
答案 1 :(得分:1)
使用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
表中的列进行分组,因为所有不匹配的行都将分组在一起。而且,如果您要过滤订单状态,显然您只需要订单中的产品。