`

mysql分组后获取若干数据

 
阅读更多

最近做一个链表分组查询,并且取每个分组的前几位数据的业务

例如有商品表,订单表,品类表,商品表中有自己的分类,并且商品表外键关联品类表主键,订单表外键关联商品表中的商品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分成子线程来查询



 

 

 

 

 

 

 

  • 大小: 41.2 KB
  • 大小: 69.2 KB
  • 大小: 72.8 KB
分享到:
评论

相关推荐

    mysql查询优化的若干

    - **COUNT(*)的优化**:当在一个表上执行`COUNT(*)`且无WHERE条件时,MySQL可以直接从表中获取相关信息而无需额外处理。 - **NOT NULL 表达式的优化**:对于单表查询,如果查询条件中包含NOT NULL表达式,MySQL也会...

    几个mysql练习题目压缩包

    这个压缩包文件"几个mysql练习题目压缩包"显然包含了若干个与MySQL相关的练习题目,旨在帮助用户提升MySQL的技能和知识。以下是一些可能涵盖的MySQL知识点: 1. 数据类型:在MySQL中,了解各种数据类型(如INT, ...

    MySQL命令大全

    MySql的用户管理是通过User表来实现的,添加新用户常用的方法有两个,一是在User表插入相应的数据行,同时设置相应的权限;二是通过GRANT命令创建具有某种权限的用户。其中GRANT的常用用法如下: grant all on mydb...

    PHP and Mysql

    2. **表的创建**:在MySQL中,使用SQL语句(如CREATE TABLE)来创建数据表,如`a_board`,并定义各列的名称和数据类型,如integer、varchar等。 3. **查询操作**:在PHP中,我们通过MySQL函数(如mysql_connect、...

    sql初级入门

    使用GROUP BY进行数据分组,HAVING子句对分组后的数据进行过滤;ORDER BY实现结果排序,ASC表示升序,DESC表示降序。 五、联接查询 当需要从多个表中获取数据时,可以使用JOIN操作。INNER JOIN返回两个表中匹配的行...

    数据库课本例题(数据查询)

    - **选择若干元组**:通过DISTINCT关键字消除重复行,例3.21展示了如何获取不同学生的学号。 - **指定查询条件**:使用比较运算符(=, &gt;, &lt;, &gt;=, , !=, BETWEEN, IN, LIKE, IS NULL)进行筛选,如例3.22至3.33中的...

    一些经典的SQL语句和各大公司的面试题

    - **HAVING**:在分组后过滤数据,类似于WHERE,但HAVING可以处理聚合函数。 - **ORDER BY**:对查询结果进行排序,可以指定升序(ASC)或降序(DESC)。 4. **连接查询**: - **INNER JOIN**:返回两个表中匹配的行...

    sql学习笔记 常见问题总结

    2. GROUP BY:用于将数据按一个或多个列进行分组,常与聚合函数一起使用。例如,`SELECT column1, COUNT(*) FROM table GROUP BY column1`按column1分组并计数。 3. HAVING:与WHERE类似,但用于筛选GROUP BY后的...

    sql学习成果Trans-sql

    1. 数据库与表:SQL中的数据库是由多个表格组成的集合,每个表格包含若干列和行,列定义了数据类型,行则是具体的数据实例。创建数据库和表需要用到`CREATE DATABASE`和`CREATE TABLE`语句。 2. 数据类型:SQL支持...

    sqlserver2000

    MySQL中的`CURDATE()`函数用于获取当前日期。 10. ** BETWEEN操作符**:用于选取在两个值范围内的记录,如`BETWEEN 2000 AND 3000`。 11. **LIKE操作符**:进行模糊查询,例如`WHERE ename LIKE 's%'`匹配以's'...

    Grid++Report6.0.0.6.rar

    用户可以直接在报表设计中嵌入SQL查询,实时获取和展示数据库中的数据,实现动态报表生成。 3. **数据统计**:内置的数据处理和计算功能使得Grid++Report能够对数据进行聚合、过滤、排序等操作,支持统计函数如平均...

    微信公众平台应用开发:方法、技巧与案例.(机械工业.柳峰)

    该书系统讲解了微信公众平台应用开发的流程、方法和技巧,并配有若干完整的案例。 全书共11章,逻辑上划分为四个部分: 第一部分(第1~2章)介绍了公众平台的使用、公众账号的认证、编辑模式的使用等基础知识。 ...

    J2EE实训教程

    - **分组:** 在实训过程中,学生会被分成若干个小组,每个小组共同完成一个项目。这种方式可以促进团队协作能力的培养。 - **写日志:** 学生需要记录实训过程中的心得体会、遇到的问题及解决办法等,这对于积累...

    The R Book

    - **分组汇总**: 应用`aggregate()`、`tapply()`等函数对数据进行分组计算。 ##### 5. 图形绘制 (Graphics) - **基本图形**: 散点图、条形图、饼图等。 - **高级图形**: 热力图、气泡图、3D图等。 - **自定义图形**...

    2021-2022计算机二级等级考试试题及答案No.17082.docx

    `GROUP BY`将数据分组,`HAVING`则在分组后进行条件筛选。题目要求查询选修了超过4门课程的学生的学号和平均成绩,因此`GROUP BY`应按照学号分组,`HAVING`后面跟着`COUNT(课程号) &gt; 3`,所以正确答案是A。 3. ...

    2021-2022计算机二级等级考试试题及答案No.16522.docx

    5. 计算机内存管理:RAM(随机访问存储器)是临时存储数据的,关机后信息会丢失。用户应该在关机前将数据保存到硬盘(非ROM,ROM是只读存储器)。 6. C语言字符编码与运算:ASCII码中数字'0'的值为48,'1'的值为49...

    京东2016实习生招聘笔试真题-技术岗位选择题二.docx

    - **K均值聚类**是一种常见的无监督学习算法,用于将相似的数据点分组到同一类别中。 - **曼哈顿距离**是指在欧几里得空间中两点沿坐标轴方向的距离之和。 **题目解析:** - 当使用曼哈顿距离作为邻近度函数时,...

    SQL 函数

    除了这些基本函数,SQL 还提供了很多其他函数,如 GROUP BY 用于分组数据,HAVING 用于筛选分组后的数据,以及更复杂的聚合函数如 STDDEV() (标准差) 和 VARIANCE() (方差) 用于统计分析。在数据库查询和数据分析中...

    易语言程序免安装版下载

    注意:静态编译后常量数据位于PE文件的.rdata段中,只可读不可写,编程时请避免修改它们。譬如以下的代码,静态编译后就可能会出现问题: a = " " GetWindowTextA(hWnd, a, 20) 正确的代码为: a = 取空白文本 ...

Global site tag (gtag.js) - Google Analytics