现在有一个需求:在2018年游戏充值记录表(字段主要有: user_name , money , game_id , 表有6000w行)查找出哪些人在某段日期内累计充值金额在100~500元范围内的,返回满足以上条件的所有用户名

具体表结构:

CREATE TABLE `pay_list_pay_2018` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`orderid` varchar(50) NOT NULL,
`user_name` varchar(50) NOT NULL,
`pay_way_id` tinyint(4) NOT NULL,
`money` float NOT NULL,
`paid_amount` float unsigned NOT NULL,
`pay_date` date NOT NULL,
`pay_time` int(11) NOT NULL DEFAULT '0',
`agent_id` int(11) NOT NULL DEFAULT '0',
`placeid` int(11) NOT NULL DEFAULT '0',
`cplaceid` varchar(50) DEFAULT NULL,
`adid` varchar(100) DEFAULT NULL,
`game_id` int(11) NOT NULL DEFAULT '0',
`server_id` int(11) NOT NULL DEFAULT '0',
`reg_date` date NOT NULL,
`reg_time` int(11) NOT NULL DEFAULT '0',
`cid` tinyint(1) NOT NULL DEFAULT '0',
`bank_type` int(11) NOT NULL DEFAULT '1',
`plat_id` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY `orderid` (`orderid`),
KEY `agent_id` (`agent_id`),
KEY `pay_date` (`pay_date`),
KEY `game_id` (`game_id`),
KEY `server_id` (`server_id`),
KEY `user_name` (`user_name`),
KEY `reg_date` (`reg_date`),
KEY `placeid` (`placeid`),
KEY `pay_way_id` (`pay_way_id`),
KEY `plat_id` (`plat_id`),
KEY `pay_time` (`pay_time`),
KEY `reg_time` (`reg_time`),
KEY `bank_type` (`bank_type`)
) ENGINE=InnoDB AUTO_INCREMENT=73555898 DEFAULT CHARSET=utf8

那么,由此快速可以用group by和sum函数筛选用户:

SELECT user_name,sum(money)  as pay_money FROM db_pay.`pay_list_pay_2018` WHERE ( `game_id` IN ('688','919','228','179') )
AND ( (`pay_time` BETWEEN '1545580800' AND '1545667200' ))
group by user_name having pay_money BETWEEN '100' and '500'

然后,对于以上sql,当pay_time范围较大火灾game_id数量较多的时候,group by需要处理的分组数量也过多(超过1000w),导致sql时间很长:



后面通过PHP脚本处理,每3天统计一次用户累计充值金额,最后再用php数组记录用户名-累计充值金额:

/**
* 对比充值分表与总表的情况
*/
public function comparePay() {
$row_0 = $row_10 = $row_50 = $row_500 = 0;
$user_names = [];
$db = DB::getInstance('pay');
$date1 = strtotime("2018-01-01");
$date2 = strtotime("2018-01-06");
for ($s_date = $date1; $s_date < $date2; $s_date+=3600*24*3 ) {
$e_date = $s_date+3600*24*3;
$sql = "SELECT user_name,sum(money) as total FROM db_pay.pay_list_pay_2018 where game_id in ('373','365','811','366','351','352','853','1260','988','1206','1232','883','871','872','881','963','884','1231','870','873','882','880','962','874','731','711','654','628','350','291','310','314','311')
and pay_time between {$s_date} and {$e_date} group by user_name";
$list = $db->find($sql);
foreach ($list as $item) {
$user_names[$item['user_name']] += $item['total'];
}
}
foreach ($user_names as $total) {
if($total>=0 && $total<10) {
$row_0++;
}else if($total>=10 && $total<50) {
$row_10++;
}else if($total>=50 && $total<500) {
$row_50++;
}else if($total>500) {
$row_500++;
}
}
echo "\n";
echo count($user_names);
echo "\n";
echo json_encode(compact('row_0','row_10','row_50','row_500'));
}

实际上,以上操作耗时也挺久的,只是将group by运算的压力转移到了PHP上,但是虽然统计日期时间段较长时,同样存在优化空间;

之后,可以考虑swoole并发执行sql或者用其他数据方法处理(待续)

mysql中group by存在局限性探讨(待续)的更多相关文章

  1. 转:深入研究mysql中group by与order by取分类最新时间内容

    鉴于项目的需要,就从网上找到该文章,文章分析得很详细也很易懂,在android里, (不知道是不是现在水平的限制,总之我还没找到在用ContentProvider时可以使用子查询),主要方法是用SQL ...

  2. 深入研究mysql中group by与order by取分类最新时间内容

    鉴于项目的需要,就从网上找到该文章,文章分析得很详细也很易懂,在android里,(不知道是不是现在水平的限制,总之我还没找到在用 ContentProvider时可以使用子查询),主要方法是用SQL ...

  3. MySQL中group by , sum , case when then 的使用

    在我们使用数据库的时候,可能会遇到需要进行统计的情况. 比如需要统计一下,下表中各个年份的胜负场数. 遇到这样的情况,我们应该怎么办呢? 在mysql中我们可以使用group by sum  case ...

  4. MYSQL中GROUP BY不包含所有的非聚合字段时的注意事项

    本文导读:在MYSQL中使用GROUP BY分组时,我们可以select 多个非聚合字段,但是这些字段不在GROUP BY中,这样的SQL查询在SQL SERVER.ORACLE中是不合理的,且会报错 ...

  5. 在MySQL中group by 是什么意思

    mysql语法中group by是什么意思? 在百度中搜索半天,最后找到一篇解释比较好的(不是博文,是百度知道,很郁闷那么多网友怎么就没人解释的清楚),链接如下: http://zhidao.baid ...

  6. MYSQL中的where ‘1=1‘ 探讨

    在学习MySQL时候,关于MySQL注入的例子 首先针对以下代码,实现的是关于sql注入时,一个普通登录所产生的的问题 package com.java.lesson02; import com.ja ...

  7. mysql中group by 的用法解析

    1. group by的常规用法 group by的常规用法是配合聚合函数,利用分组信息进行统计,常见的是配合max等聚合函数筛选数据后分析,以及配合having进行筛选后过滤. 假设现有数据库表如下 ...

  8. mysql中group by和order by混用 结果不是理想结果(转)

    文章转自 https://www.cnblogs.com/myphper/p/3767572.html 在使用mysql排序的时候会想到按照降序分组来获得一组数据,而使用order by往往得到的不是 ...

  9. MYSQL中GROUP BY的细节及SELECT语句顺序

    一.GROUP BY语句的细节 我们知道,在sql中,GROUP BY语句主要用来给数据分组,以便能对每个组进行聚集计算,但是GROUP BY也有一些限制需要知道: 1. GROUP BY字句可以包含 ...

随机推荐

  1. csv的文件excel打开长数字后面位变0的解决方法

    对于有大数字的CSV文件,应使用导入,而不是打开.这里以Excel2010为例,其它版本也可以参照: 打开Excel,此时Excel内为空白文档 点击工具栏中的[数据]→[自文本] 在“导入文本文件” ...

  2. MySQL和时间戳有关的函数

    1. MySQL 获得当前时间戳函数:current_timestamp, current_timestamp()mysql> select current_timestamp, current ...

  3. 手游包压缩技术引领手游行业实现app页游化

    近些年,掌上游戏时代已经成为全民风尚,但身为游戏开发商考虑过手游安装包大小与用户转化率之间的关系吗? 随着手机游戏市场发展愈发壮大,行业发展愈加成熟,手游厂商愈来愈多,手游产业也进入了优胜劣汰的环节, ...

  4. ubuntu配置Python-Django Nginx+uwsgi 安装配置

    安装Nginx sudo apt-get install nginx ubantu安装完Nginx后,文件结构大致为: 所有的配置文件都在 /etc/nginx下: 启动程序文件在 /usr/sbin ...

  5. Python中字符串拼接的N种方法

    python拼接字符串一般有以下几种方法: ①直接通过(+)操作符拼接 s = 'Hello'+' '+'World'+'!'print(s) 输出结果:Hello World! 使用这种方式进行字符 ...

  6. Python之配置文件读写

    ConfigParser模块 一.创建配置文件 在D盘建立一个配置文件,名字为:test.ini 内容如下: [baseconf] host=127.0.0.1 port=3306 user=root ...

  7. CanvasRenderingContext2D.imageSmoothingEnabled

    https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled 这是一个 ...

  8. Spark如何写入HBase/Redis/MySQL/Kafka

    一些概念 一个partition 对应一个task,一个task 必定存在于一个Executor,一个Executor 对应一个JVM. Partition 是一个可迭代数据集合 Task 本质是作用 ...

  9. 基于Flume+Kafka+ Elasticsearch+Storm的海量日志实时分析平台(转)

    0背景介绍 随着机器个数的增加.各种服务.各种组件的扩容.开发人员的递增,日志的运维问题是日渐尖锐.通常,日志都是存储在服务运行的本地机器上,使用脚本来管理,一般非压缩日志保留最近三天,压缩保留最近1 ...

  10. Python遇到SyntaxError: Non-ASCII character '\xe5' in file D:\eclipseworkspace\test\test_urllib2.py on line2

    写Python时遇到SyntaxError: Non-ASCII character '\xe5' in file D:\eclipseworkspace\test\test_urllib2.py o ...