问:有效地获取大表中的最旧值,最新值和每组计数吗?

时间:2019-02-23 20:01:47

标签: mysql sql

我正在寻求提高查询性能或更有效的查询设计,以获取mysql表中每组的最小值,最大值和计数。

我所需的输出是:

+---------+----------+----------+-----+
|      id | f_amount | r_amount | cnt |
+---------+----------+----------+-----+
|       1 |     1000 |      200 |   3 |
|       2 |      300 |      300 |   1 |
|       3 |      450 |      600 |   2 |
+---------+----------+----------+-----+

其中f_amount是最旧的金额,r_amount是最新的金额,cnt是该特定ID的交易次数。

我的查询[获得期望的结果,但是非常慢]。我的表有近10亿条记录,每个id本身都有成千上万的事务,所有数据都在MySQL中。

我无法使用通用表表达式来实现相同的功能。

SELECT     x.fund_id AS id, 
           min_amt AS f_amount, 
           max_amt AS r_amount, 
           z.cnt 
FROM       ( 
                  SELECT fund_id, 
                         amount AS min_amt, 
                         dt 
                  FROM   trans
                  WHERE  dt = 
                         ( 
                                SELECT Min(dt) 
                                FROM   trans g 
                                WHERE  g.fund_id = trans.fund_id)) x 
INNER JOIN 
           ( 
                  SELECT fund_id, 
                         amount AS max_amt, 
                         dt 
                  FROM   trans
                  WHERE  dt = 
                         ( 
                                SELECT Max(dt) 
                                FROM   trans g 
                                WHERE  g.fund_id = trans.fund_id)) y 
INNER JOIN 
           ( 
                    SELECT   fund_id, 
                             Count(fund_id) AS cnt 
                    FROM     trans g 
                    GROUP BY 1) z 
where      x.fund_id = y.fund_id 
AND        x.fund_id = z.fund_id 
ORDER BY   x.fund_id;

表创建和示例数据插入:

CREATE TABLE trans (
  fund_id int,
  amount int,
  dt date);



insert into trans values(1,1000,'2019-02-01');
insert into trans values(1,500,'2019-02-02');
insert into trans values(1,200,'2019-02-03');
insert into trans values(2,300,'2019-02-15');
insert into trans values(3,450,'2019-02-17');
insert into trans values(3,600,'2019-02-20');

2 个答案:

答案 0 :(得分:2)

查看您的代码和数据..似乎您需要

SELECT fund_id, Max(amount) , min(amount), count(*)
FROM   trans
group by fund_id

答案 1 :(得分:0)

使用汇总获取开始和结束日期。然后加入所需的结果:

select t.fund_id, tf.amount as first_amount, tl.amount as last_amount, t.cnt
from (select t.fund_id, min(dt) as min_dt, max(dt) as max_dt, count(*) as cnt
      from trans t
      group by t.fund_id
     ) t join
     trans tf
     on tf.fund_id = t.fund_id and tf.dt = min_dt join
     trans tl
     on tl.fund_id = t.fund_id and tl.dt = max_dt;

Here是db <>小提琴。