目录

一、背景

二、实战解析

三、总结


一、背景

最近,在开发中遇到个功能需求。系统有个资讯查询模块,要求资讯按照卡片形式展示。如下图:

按照项目组展示卡片,每个项目组展示阅读量最多的TOP2。

需求解析:按照项目组分组,然后取每组阅读量最多的前2条。

二、实战解析

基于Mysql数据库

表定义

1、项目组:team

id

主键

name

项目组名称

2、资讯表:info

id

主键

team_id

项目组id

title

资讯名称

pageviews

浏览量

content

资讯内容

info表数据如下图

我们先预习下Select基础知识

书写顺序:

select *columns*
from *tables*
where *predicae1*
group by *columns*
having *predicae1*
order by *columns*
limit *start*, *offset*;

执行顺序:

from *tables*
where *predicae1*
group by *columns*
having *predicae1*
select *columns*
order by *columns*
limit *start*, *offset*;

count(字段名) # 返回表中该字段总共有多少条记录

DISTINCT 字段名 # 过滤字段中的重复记录

第一步:先找出资讯表中阅读量的前二名

info资讯表自关联

SELECT a.* FROM info a
WHERE (SELECT count(DISTINCT b.pageviews) FROM info b WHERE a.pageviews < b.pageviews AND a.team_id= b.team_id) < 2 ;

乍一看不好理解,下面举例说明

举个例子:

当阅读量pageviews a = b = [1,2,3,4]

a.pageviews = 1,b.pageviews 可以取值 [2,3,4],count(DISTINCT b.pageviews) = 3
a.pageviews = 2,b.pageviews 可以取值 [3,4],count(DISTINCT b.pageviews) = 2 # 有2条,即第三名
a.pageviews = 3,b.pageviews 可以取值 [4],count(DISTINCT b.pageviews) = 1 # 有1条,即第二名
a.pageviews = 4,b.pageviews 可以取值 [],count(DISTINCT b.pageviews) = 0 # 有0条,即最大 第一名

count(DISTINCT b.pageviews) 代表有几个比这条值大

a.team_id= b.team_id 自关联条件,约等于分组

所以前二名 等价于 count(DISTINCT e2.Salary) < 2 ,所以 a.pageviews 可取值为 3、4,即集合前 2 高

第二步:再把表 team和表 info连接

SELECT a.id, t.NAME, a.team_id, a.pageviews FROM info a LEFT JOIN team t ON a.team_id = t.id
WHERE (SELECT count(DISTINCT b.pageviews) FROM info b WHERE a.pageviews < b.pageviews AND a.team_id= b.team_id) < 2
ORDER BY a.team_id, a.pageviews desc

结果如下图:

还有一种好理解的方式

分组GROUP BY + HAVING,这种方式可以一步一步方便调试结果

SELECT a.id, t.NAME, a.team_id, a.pageviews, COUNT( DISTINCT b.pageviews ) FROM info a LEFT JOIN info b ON ( a.pageviews < b.pageviews AND a.team_id = b.team_id ) LEFT JOIN team t ON a.team_id = t.id
GROUP BY a.id, t.NAME, a.team_id, a.pageviews
HAVING COUNT( DISTINCT b.pageviews ) < 2
ORDER BY a.team_id, a.pageviews DESC

问题:如果出现阅读数相同的情况,就裂开了

举例说明:

当阅读量pageviews a = b = [1,2,2,4]

a.pageviews = 1,b.pageviews 可以取值 [2,2,4],count(DISTINCT b.pageviews) = 3
a.pageviews = 2,b.pageviews 可以取值 [4],count(DISTINCT b.pageviews) = 1 # 有1条,即并列第二名
a.pageviews = 2,b.pageviews 可以取值 [4],count(DISTINCT b.pageviews) = 1 # 有1条,即第二名
a.pageviews = 4,b.pageviews 可以取值 [],count(DISTINCT b.pageviews) = 0 # 有0条,即最大 第一名

count(DISTINCT e2.Salary) < 2 ,所以 a.pageviews 可取值为 2、2、4,即集合前 2 高,但是有三条数据

三、总结

需求转化:将分组求前几条,改为了自关联后,有几条数据比这条大

其实这个是类似LeetCode上难度为hard的一道数据库题目

185. 部门工资前三高的所有员工

参考:

https://leetcode-cn.com/problems/department-top-three-salaries/solution/185-bu-men-gong-zi-qian-san-gao-de-yuan-gong-by-li/

关注我的公众号【Java大厂面试官】,回复:架构资源等关键词(更多关键词,关注后注意提示信息)获取更多免费资料。

公众号会发布在工作中遇到的问题和解决方案,分享自己的读书笔记和面试总结,成为一个架构师的辛酸之路,以及去大厂的面试资料和面经。

【Mysql】Sql分组查询后取每组的前N条记录相关推荐

  1. SQL分组查询后取每组的前N条记录

    本文由 Leon 同学授权发布 这个公众号的关注者除了大部分是 Android 工程师之外还有部分后端以及前端同学,我鼓励也非常欢迎大家来投稿,其实我们并不需要把自己限定在某个领域,多学学其他语言也是 ...

  2. oracle查询:分组查询,取出每组中的第一条记录

    按type字段分组,code排序,取出每组中的第一条记录 方法一: select type,min(code) from group_info  group by type; 注意:select 后面 ...

  3. SQL 分组排序后取值

    SQL 分组排序后取值 场景前要: 从前有三个班级,每个班级的学生成绩各异,有一天睿智的校长希望知道这一年中,每个班级近一年里所有的学生成绩信息,和查询每个班级近一年里所有第一名的学生成绩信息,故事由 ...

  4. MySQL SQL分组查询

    一.group by 子句 语法: select 分组函数,列(要求出现在group by)的后面 from 表 [where 筛选条件] group by 分组的列表 [order by 子句] 注 ...

  5. sql语句如何按产品类别查询,取出每个类别的前三条记录

    select * from (select *,row_number() over(partition by classid order by classid) as rownum  --上面利用ro ...

  6. mysql分组取所有数据_mysql 分组后取每个组内最新的一条数据

    首先,将按条件查询并排序的结果查询出来. mysql> select accepttime,user,job from tuser_job where user =8 order by acce ...

  7. oracle分组查询取第一条数据,160804、oracle查询:取出每组中的第一条记录

    oracle查询:取出每组中的第一条记录 按type字段分组,code排序,取出每组中的第一条记录 方法一: select type,min(code) from group_info group b ...

  8. 160804、oracle查询:取出每组中的第一条记录

    oracle查询:取出每组中的第一条记录 按type字段分组,code排序,取出每组中的第一条记录 方法一: select type,min(code) from group_info  group ...

  9. mysql提取前两个数据_各种数据库提取表的前几条记录的方法

    前一阵子去了个面试,其中有个道考题是写出取某张表前10条记录的sql语句.一头雾水,回来问了同学也没有结果,近来上网搜了一下,收获如下: 原来不同的DBMS对此操作的sql语句也不同. (取出TABL ...

最新文章

  1. 502 Server dropped connection
  2. 软件开发人员标准薪金 人月_软件产品测试周期
  3. 按需生产 ,我们准备好了吗?
  4. unity黑白滤镜_unity颜色分级图像滤镜着色器Fast Mobile Color Grading 1.0
  5. 检测是否输入字母c语言程序,C语言判断字符是否为可打印字符的方法
  6. v7000更换电池步骤_ups电源运行中是否可以更换电池?应如何操作呢
  7. python画多层网络_绘制多层n
  8. session和token的区别
  9. vscode 显示分支_Git以及vscode里的使用
  10. CPU溫度高的9種可能
  11. Python丨Python 性能分析大全
  12. (CSCD 理工科)中文科技核心期刊汇总
  13. Html5下载功能实现
  14. JLNews新闻点评系统--君兰IT
  15. 【学习日志】2022.10.08 Unity人物运动(移动+转身)、Character Controller、射线检测、动画融合
  16. 两个对象值相同(x.equals(y) == true),但却可有不同的hashCode,这句话对不对?
  17. AcWing 741. 斐波那契数列
  18. java 判断是否为英文字母_java判断是否是26个英文字母代码示例
  19. 腾达便携无线路由 无法建立到192.168.2.1的服务器连接,Tenda腾达路由器5G信号设置步骤...
  20. angular2项目里使用 Spin(加载中)

热门文章

  1. 成功没有捷径,这些在麒麟班的同学是这样学习的
  2. 如何用新浪微博账号登陆第三方网站
  3. Android--打地鼠
  4. Oracle XE简介
  5. 从文档分享看互联网重塑教育
  6. linux 时钟同步命令,Linux 时间同步服务命令
  7. 东芝为何无法成为通用电气?日媒:或在于赚钱方法
  8. Fedora 26 利用 EasyScreenCast 长时间录制桌面视频 录屏
  9. 华为 android 11,Android 11发布,华为正式官宣,新系统更值得期待!
  10. 委托律师打官司,需要准备多少钱?