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

Posted

技术标签:

【中文标题】通过 MySQL 一起获取最大记录和最小记录【英文标题】:Get max record and min record together via MySQL 【发布时间】:2020-09-09 00:47:19 【问题描述】:

拥有这样的数据集:

id inv value
1  1   10
1  2   12
1  3   4
2  1   20
2  2   2

如何编写SQL获取数据集,对于每个id,使用min inv记录减去max inv记录的值数据,数据集如下所示:

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

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

【问题讨论】:

如果您告诉我们您的表名和列类型会有所帮助;最好的方法是只显示show create table yourtablename 的输出(作为文本,而不是图像)。还有,什么mysql版本? 请在此处了解如何提问。 ***.com/help/how-to-ask 【参考方案1】:
select id, delta_value, min(inv) min_inv, max(inv) max_inv
from (
    select
        id,
        first_value(value) over (partition by id order by inv)
        - first_value(value) over (partition by id order by inv desc) delta_value,
        inv
    from foo
) foo group by id, delta_value;

【讨论】:

我要补充一点,这只适用于 MySQL 8+,因为它是引入窗口函数的版本! +1。 错误:delta_value 必须是聚合表达式或出现在 GROUP BY 子句中 @hongchangfirst 啊,加群了。如果您设置了 ONLY_FULL_GROUP_BY sql 模式,则需要这样做【参考方案2】:

您需要创建集合的子集以获得所需的值,这是 Mysql

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
         

在这里查看它的工作原理:http://sqlfiddle.com/#!9/88a4d6/2

【讨论】:

【参考方案3】:

如果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;

您甚至可以在没有子查询的情况下执行此操作(尽管性能可能不会更好):

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;

【讨论】:

【参考方案4】:

假设您的 MySQL 版本支持 window functions,您可以根据每个 id 匹配的 maxmin inv 来选择每个 id 的 maxmin 值。这尤其适用于每个 inv 的每个 id 有多个值

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;

DEMO

【讨论】:

以上是关于通过 MySQL 一起获取最大记录和最小记录的主要内容,如果未能解决你的问题,请参考以下文章

mysql 怎么获取最大值的那条记录

工作小记录

关于学习戴工的《单片机入门到精通》的小记录

lct各类操作小记录

MySQL获取分组后的TOP 1和TOP N记录

listagg小记录