通过MySQL获取最大记录和最小记录

通过MySQL获取最大记录和最小记录,mysql,sql,Mysql,Sql,拥有这样的数据集: id inv value 1 1 10 1 2 12 1 3 4 2 1 20 2 2 2 如何编写SQL来获取数据集,对于每个id,使用最小库存记录减去最大库存记录的值数据,数据集如下所示: id delta_value min_inv max_inv 1 6 1 3 2 18 1 2 请注意,max inv的值并不一定意味着max value。假设您的MySQL版本

拥有这样的数据集:

id inv value
1  1   10
1  2   12
1  3   4
2  1   20
2  2   2
如何编写SQL来获取数据集,对于每个id,使用最小库存记录减去最大库存记录的值数据,数据集如下所示:

id delta_value min_inv max_inv
1    6           1       3
2    18          1       2

请注意,max inv的值并不一定意味着max value。

假设您的MySQL版本支持
窗口函数
,您可以选择每个id的
max
min
值,基于匹配每个id的
max
min
inv。这尤其适用于每个id每个inv有多个值的情况

select id, 
       max(value)-min(value) as delta_value,
       max(inv) as max_inv, 
       min(inv) as min_inv
from (select id, 
             inv, 
             case when inv = max(inv) over (partition by id) 
                    or inv = min(inv) over (partition by id) then value  end as value
           from your_table) t
group by id;

您需要创建集合的子集以获得所需的值,这是与Mysql<8兼容的查询。使用MySql 8+可以看到@ysth提供的答案

select imm.id, 
       tmin.value-tmax.value as delta_value,
       imm.min_inv,
       imm.max_inv
  from (select id, 
               min(inv) min_inv, 
               max(inv) max_inv 
          from yourTable 
         group by id) imm 
        inner join yourTable tmin on tmin.id = imm.id
                                    and tmin.inv = imm.min_inv
        inner join yourTable tmax on tmax.id = imm.id
                                    and tmax.inv = imm.max_inv
         

查看此处的工作情况:

如果
inv
始终从
1
开始,则会想到条件聚合:

select id,
       sum(case when inv = max_inv then value
                when inv = 1 then - value
           end),
       min(inv), max(inv)
from (select t.*,
             max(inv) over (partition by id) as max_inv
      from t
     ) t
group by id;
您甚至可以在没有子查询的情况下执行此操作(尽管性能可能不会更好):


如果您告诉我们您的表名和列类型,这会有所帮助;最好的方法是只显示
show create table yourtablename
的输出(作为文本,而不是图像)。还有,什么mysql版本?请在这里学习如何提问。我想补充一点,这只适用于MySQL 8+,因为它是引入窗口功能的版本+1.错误:delta_值必须是聚合表达式或出现在GROUP BY中clause@hongchangfirst啊,把它加入了这个小组。如果设置了唯一的“完全”组“按sql模式”,则需要这样做
select id,
       sum(case when inv = max_inv then value
                when inv = 1 then - value
           end),
       min(inv), max(inv)
from (select t.*,
             max(inv) over (partition by id) as max_inv
      from t
     ) t
group by id;
select distinct id,
       (first_value(value) over (partition by id order by inv desc) -
        first_value(value) over (partition by id order by inv asc)
       ) as diff,
       min(inv) over (partition by id),
       max(inv) over (partition by id)
        
from t;