最近做一个链表分组查询,并且取每个分组的前几位数据的业务
例如有商品表,订单表,品类表,商品表中有自己的分类,并且商品表外键关联品类表主键,订单表外键关联商品表中的商品id
业务需要,根据当前时间区间进行年月周日,进行时间对比,也就是说分组第一优先为时间,其次为商品分类,再到品类,再到商品中的社群属性,一共分组条件为4组
列出关键字段
商品表字段goods_id,goods_type,main_category_id,applicable_crowd,son_category_id等
订单表字段order_id,create_date,order_price等
品类表字段id,category_name等
第一解决方案,直接根据上面所有条件进行分组然后在代码层面对数据进行二次筛选,适合小数据量,直接上sql代码
SELECT
DATE_FORMAT(o.create_date,'%Y-%m-%d') AS create_date,
o.order_id AS order_id,
COUNT(*) AS order_total,
g.goods_type AS goods_type,
g.main_category_id AS category_id,
b.category_name AS category_name,
SUM(o.order_price) AS order_price,
g.applicable_crowd AS applicable_crowd,
g.son_category_id
FROM `order` o
JOIN goods_base g
ON o.goods_id = g.goods_id
LEFT JOIN articlecategories b
ON g.main_category_id = b.id
WHERE o.is_delete = 0
AND g.is_delete = 0
AND DATE_FORMAT(o.create_date, '%Y-%m-%d') >= DATE_FORMAT('2018-05-01', '%Y-%m-%d')
AND DATE_FORMAT(o.create_date, '%Y-%m-%d') <= DATE_FORMAT('2018-05-01', '%Y-%m-%d')
GROUP BY create_date, g.goods_type,g.son_category_id,g.applicable_crowd
ORDER BY create_date,order_price DESC;
上面的结果集中DATE_FORMAT(o.create_date,'%Y-%m-%d') AS create_date,可以根据条件换成周,月,年
DATE_FORMAT(o.create_date,'%Y-%u') AS create_date周
DATE_FORMAT(o.create_date,'%Y-%m') AS create_date月
DATE_FORMAT(o.create_date,'%Y') AS create_date年
注意:这个时候,分组的条件一定是create_date而不是o.create_date,因为我们是对结果集的create_date进行分组,而不是对原有数据集的o.create_date分组,这个非常重要,同样排序的时候,我们也是对结果集的create_date和结果集中的order_price进行分组的
这种获取到的结果是按时间分组后拿出该时间段所有的数据,需要在业务层代码对其进行一定的分析后或者有用数据
第二种解决方案,需要mysql的虚拟自增id,我们对刚刚的数据集作为一张表,这张表和自己用时间段来进行自联查询获取他们的笛卡尔积,然后通建立一个虚拟自增seq,通过order_price和seq的对比来获取需要笛卡尔积中需要的数据集,本业务中是通过order_price倒序seq升序来排列的,那么条件为a.order_price<=b.order_price and a.seq>=b.seq这个逻辑可以理解成a表中的任意一条数据都能对应到b表中本身的数据和当前价格比他大但是序列号比他小,sql也是利用上面的sql进行自联查询,并赋予一个自增的seq
SELECT
a.create_date,
a.order_id,
a.order_total,
a.goods_type,
a.category_id,
a.category_name,
a.order_price,
a.applicable_crowd
FROM (
SELECT
kk.*,
(@j:=@j+1) AS seq
FROM(
SELECT
DATE_FORMAT(o.create_date,'%Y-%m-%d') AS create_date,
o.order_id AS order_id,
COUNT(*) AS order_total,
g.goods_type AS goods_type,
g.main_category_id AS category_id,
b.category_name AS category_name,
SUM(o.order_price) AS order_price,
g.applicable_crowd AS applicable_crowd,
g.son_category_id
FROM `order` o JOIN goods_base g
ON o.goods_id=g.goods_id LEFT JOIN articlecategories b ON g.main_category_id=b.id
WHERE o.is_delete=0 AND g.is_delete=0
AND DATE_FORMAT(o.create_date, '%Y-%m-%d') >= DATE_FORMAT('2018-05-01', '%Y-%m-%d')
AND DATE_FORMAT(o.create_date, '%Y-%m-%d') <= DATE_FORMAT('2018-05-01', '%Y-%m-%d')
GROUP BY create_date,
g.goods_type,g.son_category_id,g.applicable_crowd ORDER BY create_date,order_price DESC
) kk ,(SELECT @j:=0) it
) a
JOIN
(
SELECT
kk.*,
(@i:=@i+1) AS seq
FROM(
SELECT
DATE_FORMAT(o.create_date,'%Y-%m-%d') AS create_date,
o.order_id AS order_id,
COUNT(*) AS order_total,
g.goods_type AS goods_type,
g.main_category_id AS category_id,
b.category_name AS category_name,
SUM(o.order_price) AS order_price,
g.applicable_crowd AS applicable_crowd,
g.son_category_id
FROM `order` o JOIN goods_base g
ON o.goods_id=g.goods_id LEFT JOIN articlecategories b ON g.main_category_id=b.id
WHERE o.is_delete=0 AND g.is_delete=0
AND DATE_FORMAT(o.create_date, '%Y-%m-%d') >= DATE_FORMAT('2018-05-01', '%Y-%m-%d')
AND DATE_FORMAT(o.create_date, '%Y-%m-%d') <= DATE_FORMAT('2018-05-01', '%Y-%m-%d')
GROUP BY create_date,
g.goods_type,g.son_category_id,g.applicable_crowd ORDER BY create_date,order_price DESC
) kk ,(SELECT @i:=0) it
) b
ON a.create_date = b.create_date
AND a.order_price <= b.order_price
AND a.seq >= b.seq
GROUP BY a.create_date,a.goods_type,a.son_category_id,a.applicable_crowd,a.order_price
HAVING COUNT(a.order_price) <= 8
ORDER BY a.create_date,a.order_price DESC;
同样需要注意的是,在第一次分组中create_date和排序中create_date,order_price选择
这种方式是一条sql可以解决数据读取问题,并不会返回大量数据,但是在数据量稍微大一点的场景下,sql要反复对其筛选,会非常卡顿
第三种解决方案,利用代码层面和sql分开做
思路:首先根据业务层传过来的参数,进行判定是否需要拆成多个分组,将分组查询数据的条件准备好,利用CountDownLatch分成子线程来查询
相关推荐
思路:先随机排序然后再分组就好了。 1、创建表: CREATE TABLE `xdx_test` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `class` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=...
因为在mysql分组是将第一个出现的数据进行展示出。 MySQL会创建临时表的几种情况: 1、UNION查询; 2、用到TEMPTABLE算法或者是UNION查询中的视图; 3、ORDER BY和GROUP BY的子句不一样时; 4、表连接中,ORDER BY...
mysql获取分组后每组的最大值实例详解 1. 测试数据库表如下: create table test ( `id` int not null auto_increment, `name` varchar(20) not null default '', `score` int not null default 0, primary key...
Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql测试数据。Mysql...
–按某一字段分组取最大(小)值所在行的数据 代码如下: /* 数据如下: nameval memo a 2 a2(a的第二个值) a 1 a1–a的第一个值 a 3 a3:a的第三个值 b 1 b1–b的第一个值 b 3 b3:b的第三个值 b 2 b2b2b2b2 b 4 b4b4 b ...
myeclipse mysql servlet从前端获取数据myeclipse mysql servlet从前端获取数据myeclipse mysql servlet从前端获取数据myeclipse mysql servlet从前端获取数据
文件中包含项目源码,对应的数据库,以及项目运行后实现的图表截图(含url)。项目本人亲测,可完美展示图表,若有疑问,可Email我,Email:bpcforevery@gmail.com 。(ps:本人在另一个上传的文件中实现了用SSM框架...
使用jsp获取mysql数据,本人已经调试通过,里面说明了详细操作步骤,以求给正在学习这方面的同仁以帮助,稍作引路. 里面附了数据脚本文件,jdbc for mysql的驱动,Tomcat的配置文件.
这是我自己学习mysql时的学习笔记,每一个知识点都是自己动手写的,涵盖了mysql中的几乎全部的基础知识点,查询,子查询,分组,排序,常用函数,多表连接,视图,变量,存储过程,函数,分支结构,循环结构等等
Mysql数据库连接、获取数据、增删改数据操作。包括连接Mysql数据库,从数据库中获取数据,对数据增删改操作。 源代码 C#的。
这是一个android客户端从mysql数据库中获取数据的实例
用highcharts实现从mysql数据库获取数据生成实时折线图。开发平台是用eclipse实现的,是一个项目,用jsp显示从数据库读取的实时折线图。
该资源主要实现如下功能,利用poi获取excel中大量数据,然后利用jdbc批量插入到mysql
MYSQL的一个demo,可以通过VB语言运行界面来获取数据库的表格和内容,并且可以修改数据库内容及上传。
MySQL30W测试数据 MySQL30W测试数据 MySQL30W测试数据 MySQL30W测试数据
“串口数据采集入MySQL数据库”软件是传感器网络记录数据的一般工具。最主要核心功能是把串口上接收到的数据,以字符串数据...达到采集串口上获取数据存入MySQL数据库的作用,进而可以使用各种算法和方法处理这些数据。
PB11.5 从SQL语句获取数据存储Demo(数据库是用MySQL)。
Java爬虫获取网页表格数据并保存到MySQL数据库,包含完整代码
MySql实现分组取n条最大记录,还在为分组取最大困扰么?