这段 SQL 大佬能给点优化建议吗?统计一个月每天的数据还有更加简洁的写法吗?目前运行速度太慢了

2019-09-25 10:35:52 +08:00
 galaChe

SELECT su.real_name AS realName, sd.name AS deptName, su.user_name AS userName, ahh.* FROM ( SELECT ROUND( SUM( IF ( DAY ( ah.audit_time ) = '1', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '1', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '2', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '2', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '3', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '3', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '4', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '4', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '5', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '5', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '6', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '6', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '7', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '7', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '8', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '8', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '9', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '9', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '10', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '10', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '11', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '11', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '12', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '12', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '13', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '13', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '14', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '14', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '15', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '15', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '16', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '16', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '17', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '17', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '18', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '18', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '19', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '19', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '20', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '20', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '21', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '21', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '22', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '22', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '23', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '23', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '24', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '24', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '25', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '25', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '26', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '26', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '27', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '27', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '28', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '28', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '29', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '29', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '30', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '30', ROUND( SUM( IF ( DAY ( ah.audit_time ) = '31', ah.audit_num * ifnull( kpi.kpi_value, 1 ), NULL ) ), 2 ) AS '31', SUM( ( ROUND( ( ah.audit_num * ifnull( kpi.kpi_value, 1 ) ), 2 ) ) ) AS auditCount, ah.account_number AS empNumber, ah.emp_name AS employeeName, SUM( ROUND( ( ah.pass_num * ifnull( kpi.kpi_value, 1 ) ), 2 ) ) AS passCount, SUM( ROUND( ( ah.delete_Num * ifnull( kpi.kpi_value, 1 ) ), 2 ) ) AS delCount FROM audit_days AS ah LEFT JOIN skill_group_kpi AS kpi ON ( ah.group_name = kpi.group_name ) AND kpi.is_deleted = 0 WHERE 1 = 1 GROUP BY ah.account_number ORDER BY NULL ) ahh LEFT JOIN sys_user su ON su.qq LIKE concat( '%', ahh.empNumber, '%' ) AND ahh.empNumber != 0 LEFT JOIN sys_department sd ON sd.id = su.department_id

9065 次点击
所在节点    MySQL
74 条回复
nnnToTnnn
2019-09-25 11:28:34 +08:00
其次,这种粘贴复制的,连代码都不格式化一下的,我觉得这对帮你解决问题的人,很不友好.


真的是日了狗了,我严重怀疑你写代码也是不是不注重格式
mirrorpen
2019-09-25 11:30:51 +08:00
看到这一坨 SQL 语句,头皮发麻,手脚冰凉...
neoblackcap
2019-09-25 11:31:57 +08:00
粗略地看了一下,你这段 SQL 是分日期统计吧。那么就分表计算啊,每天跑定时任务,按小时,天,月分别建汇总表。你分析起来就简单了啦
ccgoing10
2019-09-25 11:32:59 +08:00
oracle 有个分析函数可以一次性把每天的数据分别汇总,你这目测不是 oracle 数据库
yusen01
2019-09-25 11:35:20 +08:00
看傻了
Yourshell
2019-09-25 11:35:24 +08:00
我就想问一下你们数据库大牛都这样处理数据的吗?
nnnToTnnn
2019-09-25 11:37:01 +08:00
@nnnToTnnn 那个 sql 大神能否讲解一下

on 和 where 的区别


我一直以为

on 是指两个表关联的条件
where 指的是过滤条件

on 使用过滤条件相比 where 查询会快吗?
lblblong
2019-09-25 11:39:26 +08:00
从你这段 sql 我只能看出我以前写的那都不叫 sql
littleshy
2019-09-25 11:42:20 +08:00
作为一个后端,我只想说:隔行如隔山。
nicevar
2019-09-25 12:03:15 +08:00
以前我也是一股脑的在 SQL 上使劲耗,后来把数据放到 MongoDb 终于消停了,有条件的话把数据同步到 MongoDb,做数据分析会减轻很大的工作量
aguesuka
2019-09-25 12:24:33 +08:00
@nnnToTnnn 以前我也纠结过这个问题,后来看学会执行计划后发现都一样
lolizeppelin
2019-09-25 12:28:42 +08:00
不换数据库没有 多核都用不了的渣渣
chengyiqun
2019-09-25 12:34:51 +08:00
这种就应该用 job 扫描数据, 然后单独按天汇总表.
dswyzx
2019-09-25 12:41:49 +08:00
fishCatcher
2019-09-25 12:44:20 +08:00
@nnnToTnnn 你竟然看完了 屌爆了
zichen
2019-09-25 13:57:04 +08:00
前公司一堆这样的 sql 语句的作业在跑,面相数据库编程……几百行的存储过程我都改过。
Macolor21
2019-09-25 14:05:07 +08:00
老哥,佩服你写 SQL 的毅力。这个要是我自己写,写完就看不懂了。

程序员最好不要写这么长的 SQL 或者代码。主要是后续维护特别麻烦,大家也没有嘲讽的意思,你冷静一点。

常用做法是开 job 跑每天任务,这样以后维护排查会方便一些,统计在一个 job 服务,查看再另一个报表,算某个方面的解耦,希望对你有帮助。
Michaelssss
2019-09-25 14:12:04 +08:00
如果觉得慢。。。还是把这种 cpu 操作移到应用服务器吧,或者用 PL/SQL 的游标可能能简化点写法。。。
magicsilence
2019-09-25 14:25:23 +08:00
sql 也是语言啊。
劝别人不要写这么长的 sql, 不如自己不要写这么长代码。
作为统计 sql 来说,这个 sql 根本不算长,真是隔行如何隔山...

我提供个思路,如果实在优化不动,可以试试 presto。
galaChe
2019-09-25 14:29:20 +08:00
@Macolor21 一些特殊对内的功能还是有很多长 SQL (形成原因也五花八门比如技术债务之类),当然我这个 SQL 确实写得不怎么样。您说的方法如果是个比较稳定的功能我也会这么写。至于没有用 MongoDB 涉及到一些多表联查不方便有些数据又写太死也不好。

至于嘲讽是开始下面有些为评论而评论,当时看了心里有些不忿。其实这个是我的原因没有发过帖子,导致 SQL 格式混乱。针对这个问题下的所有和问题相关的回答我也都感谢送铜币。

再次感谢回答,如果功能稳定我会进行数据拆分整合的。不在入口优化就在出口优化或者减少计算量还是知道的。提这个问题主要还是自己 SQL 确实写得比较少。想看看大家有没有不一样的 SQL 思路。

谢谢回答!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/603956

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX