事情是这样的,最近领导给了一个新的需求,要求在一张订单表中统计每个人第一次和第二次购买的时间间隔,最后还需要按照间隔统计计数,求出中位数等数据。

  • 由于MySQL不想Oracle那般支持行号、中位数等,所以怎么在表中统计处数据成为了关键

订单表结构,主要包含字段如下

  • id、订单号、购买人id、下单时间、商品信息字段、购买人信息字段等

1.为了方便后续统计,我的想法是构建了一张中间表,只存储一些关键字段,如购买人id,下单时间,订单号,以及购买的第几次,结构如下图:

字段解释:fans_id:购买人id、order_time:下单时间、tid:订单号、series:商品系列、shop:店铺、times:第几次购买、sync_time:同步时间、effective:是否有效、failure_time:失效时间

2.写了一段代码,处理历史订单,把所有数据按照表中格式添加进去,方便统计,每次新订单进来时,更新一下这个表即可。

3.统计:

-- 统计购买次数最大和最小
select max(times) from 统计表 where effective = '有效'
-- 统计最大购买次数间隔、最小间隔以及平均间隔(中位数的话,由于MySQL没有中位数函数,所以可以利用子查询的SQL通过程序代码计算)
SELECT
max(date) as max,
min(date) as min,
sum( date * mans ) / count( mans ) as avg
FROM
(
SELECT
ifnull(datediff( a.order_time, ( SELECT order_time FROM 统计表 WHERE times = 次数1 AND effective = '有效' AND a.fans_id = fans_id ) ),0) AS date,
a.fans_id,
1 AS mans
FROM
统计表 a
WHERE
a.times = 次数2 AND effective = '有效'
) t

4.由于接收订单后,可能状态会变,无法确保次数准确,更新统计表中每个人的次数SQL如下:

UPDATE
(SELECT @rownum:=@rownum+1 as rn,id,fans_id,order_time from
(SELECT id,fans_id,order_time from
统计表 where fans_id = 购买人 and effective = '有效'
ORDER BY order_time asc) h,
(SELECT @rownum:=0) t) t1,
statistics_repurchase t2
set t2.times=t1.rn where t2.id=t1.id;

5.由于需求还需要支持按照商品系列查询,所以需要在该表基础之上建立临时表以作统计,满足MySQL在按照某个字段分组、排序加序号

第一版SQL如下:

SELECT
a.fans_id,
a.order_time,
a.sync_time,
count( * ) AS times
FROM
统计表 AS a,
统计表 AS b
WHERE
a.fans_id = b.fans_id
AND a.order_time >= b.order_time
AND a.effective = '有效'
AND b.effective = '有效'
AND a.series LIKE concat('%','系列','%')
AND b.series LIKE concat('%','系列','%')
GROUP BY
a.fans_id,
a.id
-- 按照购买人id,按照购买时间进行排序,并标记序号,加上创建表语句如下(建表时需加索引,方便后续查找):
CREATE TABLE 临时表名 (
id INT PRIMARY KEY AUTO_INCREMENT,
fans_id VARCHAR ( 32 ),
order_time datetime,
sync_time date,
times INT ( 6 ),
PRIMARY KEY ( id ),
INDEX mid_fans_id ( fans_id ) USING BTREE,
INDEX mid_order_time ( order_time ) USING BTREE,
INDEX mid_times ( times ) USING BTREE,
INDEX mid_sync_time ( sync_time ) USING BTREE
)
AS
(
SELECT
a.fans_id,
a.order_time,
a.sync_time,
count( * ) AS times
FROM
统计表 AS a,
统计表 AS b
WHERE
a.fans_id = b.fans_id
AND a.order_time >= b.order_time
AND a.effective = '有效'
AND b.effective = '有效'
AND a.series LIKE concat('%','系列','%')
AND b.series LIKE concat('%','系列','%')
GROUP BY
a.fans_id,
a.id
);
-- 由于数据库版本为5.4,所以建完临时表不支持一条sql多次查询,没办法,只能直接创建表

结果如图:

满足了排序,但是后来我发现有一些人是同时间下单的,以至于某些人的times是重复的,于是更新为下面的SQL

SELECT
a.fans_id,
a.order_time,
a.sync_time,
( @i := CASE WHEN @pre_keyword = fans_id THEN @i + 1 ELSE 1 END ) AS times,
@pre_keyword:=fans_id
FROM
( SELECT fans_id, order_time, sync_time FROM 统计表 WHERE effective = '有效' AND series LIKE concat('%','系列','%') ORDER BY fans_id,order_time ) a,
( SELECT @i := 0, @pre_keyword := '' ) AS b

这次的sql是按照时间排序后,判断当前购买人第几次出现,打上序号,由此满足需求

查询结果和上图相同,就不附图了哈

效率这,购买人id,下单时间需要创建索引,否则可能有些慢,测试库中数据大概七百万左右,总体查询可在四秒内完成

希望这篇文章能在开发中给予您一定的帮助,新人博客主,码龄一年,如有更好的方案,望指教!

MySQL在按照某个字段分组、排序加序号的更多相关文章

  1. mysql分组排序加序号(不用存储过程,就简简单单sql语句哦)

    做前端好长时间了,好久没动sql了.在追一个喜欢的女孩,做测试的,有这么个需求求助与本屌丝,机会难得,开始折腾起来,配置mysql,建库,建表.... 一 建表 CREATE TABLE `my_te ...

  2. mysql分组排序加序号

    参照https://www.cnblogs.com/CharlieLau/p/6737243.html 一.需求 新加一个Sort 字段,初始值为1,按照parentID分组添加sort值. 根据原数 ...

  3. mysql按某一字段分组取最大(小)值所在行的数据

    mysql按某一字段分组取最大(小)值所在行的数据   mysql技巧--按某一字段分组取最大(小)值所在行的数据,这是mysql数据库程序员经常用到的在处理一些报表数据时候可以活用!那么猎微网将总结 ...

  4. MySQL使用用户变量更新分组排序

    第一个需求是根据A字段进行排序,排序结果更新到B字段 简单搜索之后,很快得到答案 http://dev.mysql.com/doc/refman/5.7/en/update.html ; ) ORDE ...

  5. MySQL进阶5--分组函数 / 分组排序和分组查询 group by(having) /order by

    MySQL进阶--分组排序和分组查询 group by(having) /order by /* 介绍分组函数 功能:用做统计使用,又称为聚合函数或组函数 1.分类: sum, avg 求和 /平均数 ...

  6. sql多字段分组排序显示全部数据

    建表sql CREATE TABLE `tbl_demo` ( `id` ) COLLATE utf8_bin NOT NULL, `payer_name` ) COLLATE utf8_bin DE ...

  7. Linux sort 多字段分组排序

    常用参数: -t: 指定分隔符 -k: 指定域 -u: 去除重复行 -n: 以数值排序 -r: 降序排序 (sort默认的排序方式是升序) -o: 结果重定向输出到文件 1.源文件: # cat hh ...

  8. mysql语句求按字段分组后组数是多少

    select count(distinct ID) from table Thinkphp CURD写 $count = $model->where($where)->count('dis ...

  9. 【MySQL作业】多字段分组和 having 子句——美和易思分组查询应用习题

    点击打开所使用到的数据库>>> 1.按照商品类型和销售地区分组统计商品数量和平均单价,并按平均单价升序显示. -- 按照商品类型和销售地区分组统计商品数量和平均单价,并按平均单价升序 ...

随机推荐

  1. PyQt(Python+Qt)学习随笔:Qt Designer中Action的信号

    Action与菜单和工具栏挂接后,只是实现了相关的关联关系,但并不能执行响应操作,真正的响应操作是通过Action的信号与对应槽函数连接实现的. Action提供了4种信号: changed()信号: ...

  2. Mybatis学习04

    title: Mybatis学习04 date: 2020-01-20 21:48:00 tags:Mybatis学习的第四篇笔记 这次的笔记主要是mybatis中的注解 <!--more--& ...

  3. 0、tensorflow学习开始

    结合tensorflowtf 2.x , tensorflow 1.x, pytorch来深入理解深度学习架构,用博客来记录这一系列,日后也方便回顾,博客中也会加入个人理解和感悟 参考的博客列表如下: ...

  4. 题解 CF1428F Fruit Sequences

    \(\texttt{Bullshit}\) 蒟蒻 \(\texttt{7 min}\) 切 \(\texttt{F}\), 挽回了本一定掉分的局面/cy 分竟然还没有别人 5 题高 (本题解为目前 c ...

  5. 从零到一快速搭建个人博客网站(域名备案 + https免费证书)(一)

    环境介绍 资源 说明 centos v7.2 docker 快速部署项目环境 nginx 反向代理,同时配置https证书 halo v1.4.2,开源博客项目 Let's Encrypt 免费证书 ...

  6. TCP 百万并发 数据连接测试 python+locust

    过程笔记和总结 尝试一.locust 测试百万Tcp并发 另一种方式是使用jmeter 基础环境 服务端 虚拟机:Centos7.2 jdk 1.8 客户端 虚拟机: Centos7.2 python ...

  7. MySQL03-多表&事务

    1.多表查询 1.1 笛卡尔积 有两个集合A,B .取这两个集合的所有组成情况. 要完成多表查询,需要消除无用的数据 1.2 多表查询分类 1.2.1 内连接查询: 1.隐式内连接:使用where条件 ...

  8. C#知识结构

    C#知识结构 对于一个工作多年的程序员而言,接口.反射.索引器.事件.委托这些耳熟能详的词汇,提起来别说多简单了,但是让老司机坐在那一个人拿起一支笔,把脑海中对C#知识结构进行梳理一下,大抵是写不了多 ...

  9. Python爬虫:爬取喜马拉雅音频数据详解

    前言 喜马拉雅是专业的音频分享平台,汇集了有声小说,有声读物,有声书,FM电台,儿童睡前故事,相声小品,鬼故事等数亿条音频,我最喜欢听民间故事和德云社相声集,你呢? 今天带大家爬取喜马拉雅音频数据,一 ...

  10. 使用 transmittable-thread-local 组件解决 ThreadLocal 父子线程数据传递问题

    在某个项目中,需要使用mybatis-plus多租户功能以便数据隔离,前端将租户id传到后端,后端通过拦截器将该租户id设置到ThreadLocal以便后续使用,代码大体上如下所示: ThreadLo ...