我想要获得状态为已发货的订单的总产品数量.如何将其编写为单个SQL查询?

表1:

id order_id product_id quantity
1 100001 123456780 3
2 100002 123456781 1
3 100002 123456782 5
4 100003 123456783 2

表2:

id order_id order_status order_date
1 100001 preparing 2023-01-26
2 100001 prepared 2023-01-26
3 100001 delivered 2023-01-26
4 100002 preparing 2023-01-26
5 100002 prepared 2023-01-26
6 100002 delivered 2023-01-26
7 100003 preparing 2023-01-26
8 100004 preparing 2023-01-26
9 100001 returned 2023-01-27

下面的SQL查询未按预期工作.因为它不会查看订单的最新状态:

SELECT SUM(t1.quantity) AS total
  FROM table_1 t1
  LEFT JOIN table_2 t2
    ON t1.order_id = t2.order_id
 WHERE t2.order_status = 'delivered'

结果:9(3+1+5)结果不正确.因为返回的是订单号100001的最后状态,所以不应该将数字3加到总数中. 正确的结果应该是6(1+5).

推荐答案

您的查询中有两个问题:

  • 您不会获取每个order_id的最新记录.您可以使用ROW_NUMBER窗口函数来实现这一点,该函数为按ORDER_DATE降序排序的每个ORDER_ID记录分配一个排名(每个ORDER_ID的LAST ORDER_DATE的rownum=1).然后您可以根据rownum=1进行筛选.
  • 您使用的是LEFT JOIN,但是您只想要在"table_2"中可以找到并且严格满足条件的行.你应该用INNER JOIN路.
WITH cte AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY order_id 
                                ORDER     BY order_date DESC, id DESC) AS rn
    FROM table_2
)
SELECT SUM(quantity)
FROM      table_1 t1
INNER JOIN cte     t2
        ON t1.order_id = t2.order_id
       AND t2.order_status = 'delivered'
       AND t2.rn = 1

如果出于某种原因不能使用公用表表达式,处理它的另一种等价方法是将CTE转换为子查询:

SELECT SUM(quantity) 
FROM       table_1 t1 
INNER JOIN (SELECT *, ROW_NUMBER() OVER(PARTITION BY order_id 
                                        ORDER BY date DESC, id DESC) AS rn 
            FROM table_2) t2 
        ON t1.order_id = t2.order_id 
       AND t2.order_status = 'delivered' 
       AND t2.rn = 1

输出:

SUM(quantity)
6

查看演示here.

Mysql相关问答推荐

MySQL查询获取图书的唯一读取页面数

如何获得表中只有最大值行的一个列被另一个列分区?

MySQL INSERT INSERT ON DIPLICATE KEY UPDATE WITH COMPAY PRIMARY KEY失败

默认情况下,MariaDB是否限制为本地主机?

如何确保 SQL 记录的列不引用它自己的主键?

如何从mysql中的不可用日期范围获取可用日期范围?

从 MySQL 8.0.12 升级到 8.0.32 时出错

for each 查询设置 MySQL @@session.time_zone 而不是 CONVERT_TZ 的缺点?

从 R 脚本创建新的 MYSQL 数据库

MySQL - 如何查询涉及前面计算值的表结果

MySQL中的会话客户端是什么

基于 3 个条件 Select 3 行的最佳 MySQL 索引和查询

如何通过if语句对SQL查询进行排序

Golang Gorm没有从关联表中检索数据

如何根据特定条件从mysql数据库中 Select 查询

SQL UPDATE中的str_replace?

在 PHP 中获取 MySQL 列的总和

Drupal 的默认密码加密方法是什么?

MySQL - 错误 1045 - 访问被拒绝

MySQL 错误 2014 的原因在其他无缓冲查询处于活动状态时无法执行查询