免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 4137 | 回复: 0
打印 上一主题 下一主题

group by 先排序再分组的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-01-04 23:40 |只看该作者 |倒序浏览

                                group by 先排序再分组的问题
group是分组,想先排序如何办?
建一个表试试
--
-- 表的结构 `test`
--
CREATE TABLE IF NOT EXISTS `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(16) NOT NULL,
  `phone` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
--
-- 导出表中的数据 `test`
--
INSERT INTO `test` (`id`, `name`, `phone`) VALUES
(1, 'a', 1234),
(2, 'a', 3333),
(3, 'b', 555),
(4, 'b', 6773),
(5, 'a', 743),
(6, 'c', 95434);
查询一下,
SELECT * FROM `test` group by name
得到
id     name     phone
1     a     1234
3     b     555
6     c     95434
但我们想得到id最大的name怎么办?
SELECT max(id),id,name,phone FROM test group by name
得到
max(id) id     name     phone
5     1     a     1234
4     3     b     555
6     6     c     95434
可以看到,虽然每个name的最大id得到了,但是,其他数据依然是每个name的第一行
用子查询
select * from (select * from test order by id desc) t group by name
得到
id     name     phone
5     a     743
4     b     6773
6     c     95434
这就是我们想要的结果了,但是,这种作法在行数非常多的情况下,相当于把整个表复制了一次,估计效率低.
那用这种子查询
select * from test t where id in  (select max(id) from test group by name)
得到
id     name     phone
4     b     6773
5     a     743
6     c     95434
然而,这种子查询因为用了in,在数量多的情况下,也许还更慢些?不确定,没时间测试
另外,还有一种方法,不过原理我也有些糊涂了,只是看网上有人这样作,
select * from test t inner join (select * from test order by id desc) t2 on t.id=t2.id group by t.name
得到
id     name     phone     id     name     phone
5     a     743     5     a     743
4     b     6773     4     b     6773
6     c     95434     6     c     95434
为了想提高效率,想到了视图,先按id desc排个视图,再group by name,岂不是相当于子查询?
CREATE VIEW `testv` AS select `test`.`id` AS `id`,`test`.`name` AS `name`,`test`.`phone` AS `phone` from `test` order by `test`.`id` desc;
视图建立了,再查询
SELECT * FROM `testv` group by name
结果竟然是
id     name     phone
1     a     1234
3     b     555
6     c     95434
和在原表用
SELECT * FROM `test` group by name
的结果一样.看来视图和真正的表毕竟是有区别的
补充:
上网再看了一下,原来第二种子查询方法网上不是那样的,尽管我那样写在这个例子上也成功了,但是,说不定其他表会错?没时间测试.网上的方法是
select * from test t inner join (select max(id) as id,name from test group by name) t2 on t.id=t2.id and t.name=t2.name
得到
id     name     phone     id     name
5     a        743          5     a
4     b       6773          4     b
6     c       95434         6     c
另外,把上面这些查询方法中的test表换成testv,都可以得到正确的结果,尽管order by有点不同.
上面的排序都只针对一个字段,两个及以上字段也可以采用类似于
select * from (select * from test order by id desc) t group by name
这样的方法,在子查询中可以多个字段来order by
下面删除原来的test,重建一下
--
-- 表的结构 `test`
--
CREATE TABLE IF NOT EXISTS `test` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(16) NOT NULL,
  `month` int(11) NOT NULL,
  `serial` int(11) NOT NULL,
  `other` varchar(20) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;
--
-- 导出表中的数据 `test`
--
INSERT INTO `test` (`id`, `name`, `month`, `serial`, `other`) VALUES
(1, 'a', 200807, 2, 'aaa1'),
(2, 'a', 200805, 2, 'aaa2'),
(3, 'b', 200805, 3, 'bbb3'),
(4, 'b', 200805, 4, 'bbb4'),
(5, 'a', 200805, 1, 'aaa5'),
(6, 'c', 200807, 5, 'ccc6'),
(7, 'b', 200807, 8, 'bbb7'),
(8, 'c', 200807, 3, 'ccc8'),
(9, 'a', 200805, 6, 'aaa9');
查询
select * from (select * from test order by month desc,serial desc) t group by name
得到
id     name     month     serial     other
1     a     200807     2     aaa1
7     b     200807     8     bbb7
6     c     200807     5     ccc6
换一下排序方式
select * from (select * from test order by month asc,serial desc) t group by name
得到
id     name     month     serial     other
9     a     200805     6     aaa9
4     b     200805     4     bbb4
6     c     200807     5     ccc6
都按我们的要求显示了结果
               
               
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/4891/showart_1773895.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP