在开发中经常遇到这样一类需求:取每种类型排名前几的数据。在此我简称它为组内排序。 以下,我借鉴了别人的方法并添加自己的想法,就这类问题做一下理解:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`type` varchar(255) DEFAULT NULL,
`variety` varchar(255) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
insert into test(type,variety,price)
values
('apple','gala',2.79),
('apple','fuji',0.24),
('apple','limbertwig',2.87),
('orange','valencia',3.59),
('orange','navel',9.36),
('pear','bradford',6.05),
('pear','bartlett',2.14),
('cherry','bing',2.55),
('cherry','chelan',6.33),
('cherry','own',1.03);
1.1 子查询
select from ((select from test order by price
asc) tmp) group by type;
1.2 UNION(类型少还能用,类型多或类型不定就算了吧)
(select * from test where type = 'apple' order by price
asc limit 1)
UNION
(select * from test where type = 'orange' order by price
asc limit 1)
UNION
(select * from test where type = 'pear' order by price
asc limit 1)
UNION
(select * from test where type = 'cherry' order by price
asc limit 1);
1.3 子查询 where (coung(*)) < 1
针对1.3的解读: 1).where (count(*)) = 0 以apple为例:
2).where (count(*)) < 1 以apple为例:
3).其他类型以此类推
2.1 找出每类水果价格最便宜的两个品种,这时子查询就不能用了
2.2 UNION(类型少还能用,类型多或类型不定就算了吧)
(select * from test where type = 'apple' order by price
asc limit 2)
UNION
(select * from test where type = 'orange' order by price
asc limit 2)
UNION
(select * from test where type = 'pear' order by price
asc limit 2)
UNION
(select * from test where type = 'cherry' order by price
asc limit 2);
2.3 子查询 where (coung(*)) < 2 select from test a where (select count() from test b where a.type = b.type and b.price < a.price) < 2;
针对2.3的解读: 1).where (count(*)) < 2 以apple为例:
2).其他类型以此类推
总结一下
:在 where 条件中关联本类型并 count(*) 的方法最为灵活,推荐使用这种方法来解此类问题。推荐方法并没有对每种类型中进行排序啊!说好的组内排序呢……,好吧在最外层套一个 order_by price asc 就好了,本文意在为这类问题提供解决方案,请不要在意这个细节 ^-^