--按某一字段分组取最大(小)值所在行的数据
/*
数据如下:
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.val
select 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
1
/*
2
数据如下:
3
name val memo
4
a 2 a2(a的第二个值)
5
a 1 a1--a的第一个值
6
a 1 a1--a的第一个值
7
a 3 a3:a的第三个值
8
a 3 a3:a的第三个值
9
b 1 b1--b的第一个值
10
b 3 b3:b的第三个值
11
b 2 b2b2b2b2
12
b 4 b4b4
13
b 5 b5b5b5b5b5
14
15
*/
16
附: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