关于一条SQL语句的优化

MySql 码拜 8年前 (2016-05-16) 1067次浏览
目前有这样一张表,查询要求:查询出当每个用户交易金额累计达到70时的交易时间。
源码:

DROP TABLE IF EXISTS t_g;
CREATE TABLE t_g
(t_id BIGINT AUTO_INCREMENT,
 t_userid VARCHAR(20) DEFAULT "" COMMENT "用户id",
 t_je VARCHAR(20) DEFAULT "" COMMENT "交易金额",
 t_date VARCHAR(20) DEFAULT "" COMMENT "交易时间",
 PRIMARY KEY(t_id)
);
-- 创建索引
CREATE INDEX i_a ON t_g (t_userid,t_date);
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","20","20160701");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","10","20160702");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","15","20160703");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","15","20160704");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","20","20160705");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","50","20160706");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","20","20160707");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("A","20","20160708");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("B","40","20160701");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("B","20","20160702");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("B","15","20160703");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("B","15","20160704");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("C","20","20160701");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("C","50","20160702");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("C","20","20160703");
INSERT INTO t_g (t_userid,t_je,t_date) VALUES ("C","20","20160704");

本人的查询语句是这样的写的:

select x.t_userid,MIN(x.t_date) from
(select a.t_userid,a.t_date,(select sum(t_je) from t_g where t_userid = a.t_userid and t_date <= a.t_date 
)total from t_g a)x 
where x.total/100 > 70  GROUP BY x.t_userid;

这样写可以是实现查询的功能,但是这张表有30万数据的时候,运行速度超级慢,大致需要2分钟。问一下高手们,这句该怎样优化,或有其他更好的办法实现没,用存储过程也可以,只要能提升性能。

解决方案

5

select t.user_id,t.date_id from (select t_userid as user_id,t_date as date_id,sum(t_je) as threadhold from t_g group by t_userid,t_date) as t where t.threadhold>=70
PS:t_date => datetime类型
t_je=>decimal类型

10

引用:
mysql> select * from t_g;
+--+--+--+--+
| t_id | t_userid | t_je | t_date   |
+--+--+--+--+
|    1 | A        | 20   | 20160701 |
|    2 | A        | 10   | 20160702 |
|    3 | A        | 15   | 20160703 |
|    4 | A        | 15   | 20160704 |
|    5 | A        | 20   | 20160705 |
|    6 | A        | 50   | 20160706 |
|    7 | A        | 20   | 20160707 |
|    8 | A        | 20   | 20160708 |
|    9 | B        | 40   | 20160701 |
|   10 | B        | 20   | 20160702 |
|   11 | B        | 15   | 20160703 |
|   12 | B        | 15   | 20160704 |
|   13 | C        | 20   | 20160701 |
|   14 | C        | 50   | 20160702 |
|   15 | C        | 20   | 20160703 |
|   16 | C        | 20   | 20160704 |
+--+--+--+--+
16 rows in set (0.00 sec)
mysql> select *
    -> from t_g t
    -> where (select sum(t_je) from t_g where t_userid=t.t_userid and t_date<t.t_date)<70
    -> and (select sum(t_je) from t_g where t_userid=t.t_userid and t_date<t.t_date)>=70-t.t_je;
+--+--+--+--+
| t_id | t_userid | t_je | t_date   |
+--+--+--+--+
|    5 | A        | 20   | 20160705 |
|   11 | B        | 15   | 20160703 |
|   14 | C        | 50   | 20160702 |
+--+--+--+--+
3 rows in set (0.00 sec)
mysql>

.

5

不如再加一列叫累计消费金额,那样会比较方便

10

你的 t_userid 有多少? 假如很多,那说明返回的数据多,查询慢也比较正常
另外,假如你的每个 t_userid 的记录需要累计达到限额的记录也非常多的话,那么查询慢也正常
假如设计上能够加累计金额,确实会方便很多,不用实时算,也能索引

10

引用:

不如再加一列叫累计消费金额,那样会比较方便

假如有这一列,就可以写
SELECT T_USERID, T_DATE, T_AGGREGATED_AMT
FROM T_G
WHERE MIN(T_AGGREGATED_AMT) >=70
GROUP BY T_USERID, T_DATE


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明关于一条SQL语句的优化
喜欢 (0)
[1034331897@qq.com]
分享 (0)