`
MauerSu
  • 浏览: 494786 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

mysql查询 分组后前 N条数据

 
阅读更多
源:http://www.jb51.net/article/31590.htm
评:
msql in的子查询内无法用limit
mysql分组 取前N条数据 语句
select a.* from tb a where N > (select count(*) from tb where name = a.name and val > a.val ) order by a.name,a.val


create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a',    2,   'a2(a的第二个值)')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    1,   'a1--a的第一个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('a',    3,   'a3:a的第三个值')
insert into tb values('b',    1,   'b1--b的第一个值')
insert into tb values('b',    3,   'b3:b的第三个值')
insert into tb values('b',    2,   'b2b2b2b2')
insert into tb values('b',    4,   'b4b4')
insert into tb values('b',    5,   'b5b5b5b5b5')
mysql分组 取前2条数据 语句
select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name,a.val


--按某一字段分组取最大(小)值所在行的数据
复制代码 代码如下:

/*
数据如下:
name val 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 5 b5b5b5b5b5
*/

--创建表并插入数据:
复制代码 代码如下:

create table tb(name varchar(10),val int,memo varchar(20))
insert into tb values('a', 2, 'a2(a的第二个值)')
insert into tb values('a', 1, 'a1--a的第一个值')
insert into tb values('a', 3, 'a3:a的第三个值')
insert into tb values('b', 1, 'b1--b的第一个值')
insert into tb values('b', 3, 'b3:b的第三个值')
insert into tb values('b', 2, 'b2b2b2b2')
insert into tb values('b', 4, 'b4b4')
insert into tb values('b', 5, 'b5b5b5b5b5')
go

--一、按name分组取val最大的值所在行的数据。
复制代码 代码如下:

--方法1:select a.* from tb a where val = (select max(val) from tb where name = a.name) order by a.name
--方法2:
select a.* from tb a where not exists(select 1 from tb where name = a.name and val > a.val)
--方法3:
select a.* from tb a,(select name,max(val) val from tb group by name) b where a.name = b.name and a.val = b.val order by a.name
--方法4:
select a.* from tb a inner join (select name , max(val) val from tb group by name) b on a.name = b.name and a.val = b.val order by a.name
--方法5
select a.* from tb a where 1 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name
/*
name val memo
---------- ----------- --------------------
a 3 a3:a的第三个值
b 5 b5b5b5b5b5

*/

本人推荐使用1,3,4,结果显示1,3,4效率相同,2,5效率差些,不过我3,4效率相同毫无疑问,1就不一样了,想不搞了。

--二、按name分组取val最小的值所在行的数据。
复制代码 代码如下:

--方法1:select a.* from tb a where val = (select min(val) from tb where name = a.name) order by a.name
--方法2:
select a.* from tb a where not exists(select 1 from tb where name = a.name and val < a.val)
--方法3:
select a.* from tb a,(select name,min(val) val from tb group by name) b where a.name = b.name and a.val = b.val order by a.name
--方法4:
select a.* from tb a inner join (select name , min(val) val from tb group by name) b on a.name = b.name and a.val = b.val order by a.name
--方法5
select a.* from tb a where 1 > (select count(*) from tb where name = a.name and val < a.val) order by a.name
/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
b 1 b1--b的第一个值

*/

--三、按name分组取第一次出现的行所在的数据。
复制代码 代码如下:

select a.* from tb a where val = (select top 1 val from tb where name = a.name) order by a.name
/*
name val memo
---------- ----------- --------------------
a 2 a2(a的第二个值)
b 1 b1--b的第一个值
*/

--四、按name分组随机取一条数据。
复制代码 代码如下:

select a.* from tb a where val = (select top 1 val from tb where name = a.name order by newid()) order by a.name/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
b 5 b5b5b5b5b5

*/

--五、按name分组取最小的两个(N个)val
复制代码 代码如下:

select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val < a.val ) order by a.name,a.valselect a.* from tb a where val in (select top 2 val from tb where name=a.name order by val) order by a.name,a.val
select a.* from tb a where exists (select count(*) from tb where name = a.name and val < a.val having Count(*) < 2) order by a.name
/*
name val memo
---------- ----------- --------------------
a 1 a1--a的第一个值
a 2 a2(a的第二个值)
b 1 b1--b的第一个值
b 2 b2b2b2b2

*/

--六、按name分组取最大的两个(N个)val
复制代码 代码如下:

select a.* from tb a where 2 > (select count(*) from tb where name = a.name and val > a.val ) order by a.name,a.val
select a.* from tb a where val in (select top 2 val from tb where name=a.name order by val desc) order by a.name,a.val
select a.* from tb a where exists (select count(*) from tb where name = a.name and val > a.val having Count(*) < 2) order by a.name
/*
name val memo
---------- ----------- --------------------
a 2 a2(a的第二个值)
a 3 a3:a的第三个值
b 4 b4b4
b 5 b5b5b5b5b5
*/


--七,假如整行数据有重复,所有的列都相同(例如下表中的第5,6两行数据完全相同)。
按name分组取最大的两个(N个)val
复制代码 代码如下:

/*
数据如下:
name val memo
a 2 a2(a的第二个值)
a 1 a1--a的第一个值
a 1 a1--a的第一个值
a 3 a3:a的第三个值
a 3 a3:a的第三个值
b 1 b1--b的第一个值
b 3 b3:b的第三个值
b 2 b2b2b2b2
b 4 b4b4
b 5 b5b5b5b5b5

*/


附:mysql “group by ”与"order by"的研究

这两天让一个数据查询难了。主要是对group by 理解的不够深入。才出现这样的情况
这种需求,我想很多人都遇到过。下面是我模拟我的内容表

我现在需要取出每个分类中最新的内容
select * from test group by category_id order by `date`

结果如下

明显。这不是我想要的数据,原因是msyql已经的执行顺序是

引用

写的顺序:select ... from... where.... group by... having... order by..
执行顺序:from... where...group by... having.... select ... order by...

所以在order by拿到的结果里已经是分组的完的最后结果。
由from到where的结果如下的内容。

到group by时就得到了根据category_id分出来的多个小组


到了select的时候,只从上面的每个组里取第一条信息结果会如下

即使order by也只是从上面的结果里进行排序。并不是每个分类的最新信息。
回到我的目的上 --分类中最新的信息
根据上面的分析,group by到select时只取到分组里的第一条信息。有两个解决方法
1,where+group by(对小组进行排序)
2,从form返回的数据下手脚(即用子查询)

由where+group by的解决方法
对group by里的小组进行排序的函数我只查到group_concat()可以进行排序,但group_concat的作用是将小组里的字段里的值进行串联起来。
select group_concat(id order by `date` desc) from `test` group by category_id


再改进一下
select * from `test` where id in(select SUBSTRING_INDEX(group_concat(id order by `date` desc),',',1) from `test` group by category_id ) order by `date` desc



子查询解决方案
select * from (select * from `test` order by `date` desc) `temp`  group by category_id order by `date` desc




分享到:
评论

相关推荐

    mysql使用GROUP BY分组实现取前N条记录的方法

    主要介绍了mysql使用GROUP BY分组实现取前N条记录的方法,结合实例形式较为详细的分析了mysql中GROUP BY分组的相关使用技巧,需要的朋友可以参考下

    MySQL获取所有分类的前N条记录

    本文给大家分享的是使用mysql实现获取所有分类的前N条记录的方法,本文给出了3个示例,有需要的小伙伴可以参考下。

    MySql基本查询、连接查询、子查询、正则表达查询讲解

    查询数据是指从数据库中的数据表或视图中获取所需要的数据,在mysql中,可以使用SELECT语句来查询数据。根据查询条件的不同,数据库系统会找到不同的数据。 SELECT语句的基本语法格式如下: [sql] view plain copy ...

    mysql获取group by总记录行数的方法

    一般来说,mysql获取group by内部可以获取到某字段的记录分组统计总数,而无法统计出分组的记录数。 mysql中可以使用SQL_CALC_FOUND_ROWS来获取查询的行数,在很多分页的程序中都这样写: 代码如下:SELECT COUNT(*) ...

    MySQL命令大全

    2)、查询前几行数据 例如:查看表 MyClass 中前行数据 mysql&gt; select * from MyClass order by id limit 0,2; 或者: mysql&gt; select * from MyClass limit 0,2; 6、删除表中数据 命令:delete from 表名 ...

    MySQL 5权威指南(第3版) 中文版 下载地址

     10.11 对前n条或后n条记录进行处理  10.12 以随机方式选择数据记录  10.13 全文索引  10.14 锁定  10.15 事务  第11章 访问权限与信息安全  11.1 简介  11.2 急救  11.3 访问控制机制的内部工作...

    mysql数据库的基本操作语法

    update主要完成对数据的修改操作,可以修改一条或多条数据。修改多条或指定条件的数据,需要用where条件来完成。 修改所有数据 update temp set name = ‘jack2’; 所有的数据的name会被修改,如果修改多列用“,”...

    MySQL5 权威指南第3版中文版_part1

     10.11 对前n条或后n条记录进行处理  10.12 以随机方式选择数据记录  10.13 全文索引  10.14 锁定  10.15 事务  第11章 访问权限与信息安全  11.1 简介  11.2 急救  11.3 访问控制机制的内部工作原理  ...

    MYSQL常用命令大全

    2)、查询前几行数据 例如:查看表 MyClass 中前2行数据 mysql&gt; select * from MyClass order by id limit 0,2; 或者: mysql&gt; select * from MyClass limit 0,2; 6、删除表中数据 命令:delete from 表名 where ...

    mysql获取group by的总记录行数另类方法

    mysql获取group by内部可以获取到某字段的记录分组统计总数,而无法统计出分组的记录数。 mysql的SQL_CALC_FOUND_ROWS 使用 获取查询的行数 在很多分页的程序中都这样写: 代码如下 SELECT COUNT(*) from `table` ...

    MySQL 入门学习 ——基础教程

    当命令输入错误而又无法改变(多行语句情形)时,只要在分号出现前就可以用 c来取消该条命令 mysql&gt; select -&gt; user() -&gt; c mysql&gt; 这是一些最常用的最基本的操作命令,通过多次练习就可以牢牢掌捂了。 ...

    PHP程序开发范例宝典III

    实例207 查询后n条记录 324 实例208 查询从指定位置开始的n条记录 325 实例209 查询统计结果中的前n条记录 326 8.6 查询周期、日期 328 实例210 查询指定时间段的数据 328 实例211 按月查询统计数据 329...

    MySQL基于group_concat()函数合并多行数据

    一个很有用的函数  group_concat(),手册上说明:... 比如在student表中,有如下5条数据:    有要求如下:“小明”的两行成绩可以放在一行展示,“小红”的两行成绩也放在一行展示!  那么就可以使用  SELECT n

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part1

    实例171 选中单选按钮后显示其他表单元素 205 实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 ...

    PHP开发实战1200例(第1卷).(清华出版.潘凯华.刘中华).part2

    实例171 选中单选按钮后显示其他表单元素 205 实例172 不提交表单获取单选按钮的值 207 实例173 实现复选框中的全选、反选和不选 208 实例174 隐藏域提交用户的ID值 210 实例175 图像域替代提交按钮 211 实例176 ...

    R语言经典实例(中+英)

     4.13 读取MySQL数据库中的数据 100  4.14 保存和传送目标 102  第5章 数据结构 104  5.1 对向量添加数据 111  5.2 在向量中插入数据 112  5.3 理解循环规则 113  5.4 构建因子(即分类变量) 115  5.5 将多...

    MYSQL,SQLSERVER,ORACLE常用的函数

    取数字n的符号,大于0返回1,小于0返回-1,等于0返回0 SQL&gt; select sign(123),sign(-100),sign(0) from dual; SIGN(123) SIGN(-100) SIGN(0) --------- ---------- --------- 1 -1 0 30.SIN 返回一个数字的正弦...

    2009达内SQL学习笔记

    多数DBMS不需要在单条SQL语句后加分号,但特定的DBMS可能必须在单条SQL语句后加分号。 SQL语句的最后一句要以 “;”号结束 二、写子句顺序 Select column,group_function From table [Where condition] ...

Global site tag (gtag.js) - Google Analytics