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' 字段上过滤产品视图。
下图显示了我们想要的结果集,基于上面的结果。红色表示它应该不是结果的一部分。
如上图所示;
- ID为18的商品重复3次,状态相同。我们只想要其中一排。
- ID 为 19 的产品出现在 3 行中,其中两行状态相同。保留两行中状态相同的一行,状态为1的行。
- ID为20的商品重复了两次,状态相同,保留一个。
如何实现?
如果你是运行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 join
和 left join
在这里没有意义。要么使用两个 inner join
s(如上述查询),要么使用两个 left join
s 如果您想保留没有任何订单的产品。
使用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 的列分组,因为所有不匹配的行都将分组在一起。如果您根据订单状态进行过滤,您显然只需要订单中的产品。
我们有一个产品、订单、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' 字段上过滤产品视图。
下图显示了我们想要的结果集,基于上面的结果。红色表示它应该不是结果的一部分。
如上图所示;
- ID为18的商品重复3次,状态相同。我们只想要其中一排。
- ID 为 19 的产品出现在 3 行中,其中两行状态相同。保留两行中状态相同的一行,状态为1的行。
- ID为20的商品重复了两次,状态相同,保留一个。
如何实现?
如果你是运行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 join
和 left join
在这里没有意义。要么使用两个 inner join
s(如上述查询),要么使用两个 left join
s 如果您想保留没有任何订单的产品。
使用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 的列分组,因为所有不匹配的行都将分组在一起。如果您根据订单状态进行过滤,您显然只需要订单中的产品。