
SegmentFault: https://segmentfault.com/q/1010000018986285
已经使用 Google 搜索过,没找到合适的答案(有些看不懂)
表字段:
id是用户唯一 idreg_time是用户注册时间戳
mysql> SELECT id,reg_time FROM `apps_user` ; +----+------------+ | id | reg_time | +----+------------+ | 1 | 1524322845 | | 2 | 1524322945 | | 3 | 1524323277 | | 4 | 1524325325 | | 5 | 1524325451 | | 6 | 1524325517 | | 7 | 1524340390 | | 8 | 1524346779 | | 9 | 1524346875 | | 10 | 1524419896 | | 11 | 1524456557 | | 12 | 1524456564 | | 13 | 1524456663 | | 14 | 1524499581 | | 15 | 1524504637 | | 16 | 1524504718 | | 17 | 1524523875 | | 18 | 1524528715 | | 19 | 1524542755 | | 20 | 1524543480 | +----+------------+ 20 rows in set (0.00 sec) 例如,我想要近 7 天中每一天的用户注册量,预想返回结果如下(这里的预想返回结果与开头表的数据无关联):
+-------------+-------+ | date | total | +-------------+-------+ | 2019-04-19 | 3 | | 2019-04-20 | 0 | | 2019-04-21 | 0 | | 2019-04-22 | 8 | | 2019-04-23 | 0 | | 2019-04-24 | 9 | | 2019-04-25 | 2 | 请大神解答,先谢谢了!
在这里统一回复下,我应该算是个业余开发(或者根本不算吧=.=),凭自己兴趣写了个小项目,写后台时,需要用折线图展现出近 7 日等某个时间范围内的每天的注册人数。
最开始想到是一天天去 count,但我个人觉得对性能有一些影响; 然后想着有没有办法直接查询一次就能获取到指定时间范围内每一天的用户注册量,接着去 Google 搜,翻了几页,没有找到合适的答案,然后就在 SegmentFault 上提问,然后又发到 v2ex
总结,我还是太年轻,也向各位大佬学习了
1 lihongjie0209 2019-04-25 15:45:53 +08:00 你应该不是开发吧 |
2 momo1999 2019-04-25 15:46:07 +08:00 先搞个任务,把每一天的注册人数写一个表里面,然后 7 天什么的都是小意思。 |
3 glacer 2019-04-25 15:50:31 +08:00 时间戳转成 date,然后 group by |
4 kisshere 2019-04-25 15:51:30 +08:00 via Android 保持队形,你应该不是开发吧 |
5 luozic 2019-04-25 15:53:03 +08:00 mysql 按时间段统计(年,季度,月,天,时) 按年汇总,统计: select sum(mymoney) as totalmoney, count(*) as sheets from mytable group by date_format(col, '%Y'); 按月汇总,统计: select sum(mymoney) as totalmoney, count(*) as sheets from mytable group by date_format(col, '%Y-%m'); 按季度汇总,统计: select sum(mymoney) as totalmoney,count(*) as sheets from mytable group by concat(date_format(col, '%Y'),FLOOR((date_format(col, '%m')+2)/3)); select sum(mymoney) as totalmoney,count(*) as sheets from mytable group by concat(date_format(col, '%Y'),FLOOR((date_format(col, '%m')+2)/3)); 按小时: select sum(mymoney) as totalmoney,count(*) as sheets from mytable group by date_format(col, '%Y-%m-%d %H '); 查询 本年度的数据: SELECT * FROM mytable WHERE year(FROM_UNIXTIME(my_time)) = year(curdate()) 查询数据附带季度数: SELECT id, quarter(FROM_UNIXTIME(my_time)) FROM mytable; 查询 本季度的数据: SELECT * FROM mytable WHERE quarter(FROM_UNIXTIME(my_time)) = quarter(curdate()); 本月统计: select * from mytable where month(my_time1) = month(curdate()) and year(my_time2) = year(curdate()) 本周统计: select * from mytable where month(my_time1) = month(curdate()) and week(my_time2) = week(curdate()) N 天内记录: WHERE TO_DAYS(NOW())-TO_DAYS(时间字段)<=N 本篇文章来源于 Linux 公社网站(www.linuxidc.com) 原文链接: http://www.linuxidc.com/Linux/2012-11/74145.htm |
6 dovme 2019-04-25 15:53:16 +08:00 用 date_format(date, format) 将注册时间转化为 2019-04-19 这样的格式,然后 groupby |
7 CallMeReznov 2019-04-25 15:54:59 +08:00 想当年我运维入职,老板让我上线上 SQLSERVER 服务器查东西.手抖的一批... 不过还好我知道有个 count() |
8 cjlmwcy 2019-04-25 15:56:06 +08:00 你应该不是开发吧 |
9 goodbye1014ac 2019-04-25 16:03:44 +08:00 你应该不是开发吧 |
10 misaka19000 2019-04-25 16:16:56 +08:00 在写数据的时候把 年、年-月、年-月-日 这种数据结构写到数据库中,之后可以直接使用 group 来进行搜索 |
11 kifile 2019-04-25 16:18:56 +08:00 你应该不是开发吧 |
12 cjlmwcy 2019-04-25 16:24:37 +08:00 SELECT COUNT(u.id) AS total, DATE_FORMAT( FROM_UNIXTIME(u.reg_time), '%Y-%m-%d' ) AS date FROM apps_user AS u WHERE FROM_UNIXTIME(u.reg_time) >= DATE_ADD(NOW(), INTERVAL - 7 DAY) GROUP BY date |
13 richChou 2019-04-25 16:30:17 +08:00 甚至可能都不是资深产品经理 |
14 thisisgpy 2019-04-25 16:35:10 +08:00 你这问题吓得我一度怀疑自己到底会不会做开发 |
15 liuzhaowei55 2019-04-25 16:48:22 +08:00 楼上那些讽刺楼主的都是臭傻逼,有一个算一个。 二楼的做法是一个解决方案,主要问题就是如果某一天没有用户注册,直接用 SQL 是无法查询出来这天的统计数据的,所以需要结合逻辑解决问题,不能直接通过 SQL 获得最终结果。 |
16 junan0708 2019-04-25 16:56:04 +08:00 |
17 liuzhaowei55 2019-04-25 17:00:15 +08:00 @junan0708 首先表示感谢,其次就是希望下次不会遇到有人问统计半年内结果怎么办的问题了。 |
18 F281M6Dh8DXpD1g2 2019-04-25 17:04:45 +08:00 @liuzhaowei55 一个比较简单的做法是先做个日期表,然后用注册表左关联之后就可以补零了 另外讽刺楼主不对,张嘴就骂人也不对,与诸君共勉了 |
19 liuzhaowei55 2019-04-25 17:09:45 +08:00 @liprais 就是看不惯讽刺的这些人,自己没有真实的处理过这种问题,只看楼主描述不懂难点问题在哪里可以理解,你不要讲话就好了,自然会有明白的人出来解决问题比如二楼,现在我就想那个讽刺楼主的人,自己好好想想这个问题怎么解决吧,自己真实遇到这个问题了是不是能很好的解决。 |
20 Patrick95 2019-04-25 17:11:46 +08:00 还腆着脸嘲讽楼主,楼主起码有开源项目。 你们呢,就一张嘴吗 |
21 neoblackcap 2019-04-25 17:27:37 +08:00 用 SQL 实现不是不行,不过太复杂了,而且不好维护。像 12 楼的写法,过一个月之后再来看看没有注释的版本,大家觉得可以一眼就看出是怎么回事? 老实建汇总表,那么天天跑个定时任务脚本就可以了,简单易维护。 |
22 yjxjn 2019-04-25 17:29:12 +08:00 |
23 fangxing204 2019-04-25 17:40:34 +08:00 via Android 可以直接 group by 按范围的,https://stackoverflow.com/q/21421973/5615038 |
24 mamahaha 2019-04-25 18:18:15 +08:00 如果用 laravel,这个很方便,可以查询介于时间戳 xxxxxxxx 和 yyyyyyyyy 之间生成的用户 DB::table('users')->whereBetween('created_at',[ xxxxxxxxx,yyyyyyyyyy])->get(); |
25 victrec 2019-04-25 18:57:45 +08:00 最直接的时间戳转成时间再按情况取年月日进行 GROUP BY。不过具体到用,还得看数据多不多,多的话这么搞要炸,楼上说的对,写定时任务记下每天的数量,数据多了每小时统计一把。 |
26 Raymon111111 2019-04-25 19:04:01 +08:00 如果只需要数量的话就缓存是最简单的 每天一个 key, 注册一个 +1 然后要什么 7 天 30 天的数据就直接在缓存里找就行了 如果需要更快捷的就再每天 0 点的时候算一个统计的数量 |
27 funky 2019-04-25 19:06:03 +08:00 redis bitmap |
28 lihongjie0209 2019-04-25 20:23:47 +08:00 @yjxjn 我就是说了一下 楼主应该不是开发 这就是嘲讽了?有多玻璃心啊 这种问题本来就是一个应用开发应该知道的: 1. 要么数据库查询的时候先转化成 date 类型, 再 groupBy, 数据量大的话可能会有性能问题 2. 要么数据库查询的时候直接用 时间戳 范围, 再在代码里面汇总。 3. 至于说定时任务和汇总表, 其实原理和上面的一样, 不过就是加了一个缓存而已。 这个问题的本质就是时间戳和日期的转化, 作为一个应用开发不知道时间戳?我怀疑楼主不是开发而可能是其他岗位临时使用数据库而已。 屁大点事,就 JJYY 的。 |
29 bwn123 2019-04-25 22:12:37 +08:00 不说动手能力,你应该连了解都没了解过开发流程吧 |
30 jessun1990 2019-04-26 09:31:28 +08:00 via iPhone 你应该是产品! |
31 ccl945 2019-04-26 10:30:18 +08:00 别解释了,你就是一个前台客服! |
32 jswh 2019-04-26 11:48:17 +08:00 让开发下载下来然后 excel 处理 |
35 NowTime OP @shuax @liuzhaowei55 @neoblackcap @Raymon111111 感谢各位建议,我算是业余的开发吧...我只是凭自己兴趣写的一个小小的项目,我以为能够直接使用 SQL 语句查询到每天的返回会结果,结果我还是太年轻,向各位大佬学习了! |
36 GreatLiXin 2019-07-11 15:53:01 +08:00 @NowTime 我有一个比较省力的解法,今天我和你遇到了同样的问题 我们要统计每一天的 testCase Fail 的数量,同样,有时候会没有 Fail 的 case,这时候就会发现当天的日期直接在查询结果中消失。 在想了一下午后,我写出来了如下查询语句。很快捷也很简单。 ``` SELECT count(IF(status = false,true,null)) AS "Fail" FROM function_test GROUP BY date_time ``` |