开发者

SQL Query help - 10 records for each distinct column value

I have a cars tab开发者_运维技巧le which contains car listings. The table structure looks something like:

 cars
   - id
   - title
   - make
   - year

I would like a query which returns 10 cars of each make.

Something equivalent to the following pseudo code:

car_makes = select distinct make from cars
for each make in car_makes 
  select id, title, make from clcars where make = $make limit 10;
end

Here's what I've tried unsuccessfully:

select id,title,make 
from cars where make in 
                    (select distinct make from cars) 
group by make;

--- This returns only one record per make.

select a.id,a.title,a.make 
from cars a left join  
 (select distinct make from cars) car_make 
   on a.make = car_make.make;

This returns every record.

I need only 10 records per car make.

Thanks for your help


This will give you what you want:

set @prev := '', @i := 0;
select  make, id, title, year
from (select id, title, make, year, (@i := if(@prev = make, @i + 1, 0)) as idx, (@prev := make)
from (select id, title, make, year from cars order by make, id) ordered) indexed
where idx < 10

To alter the choice of which 10 rows to get, change the order by of the inner-most query; I chose id order by make, id, but you could choose year. As long as make is first it will work. You could leave off anything else for a "random" pick. Order the final result as you wish.

How this works:

  • The inner-most query simply orders the rows ready for numbering - aliased as ordered
  • The next wrapper query calculates the row number (@i - counting from zero) within the make group - aliased as indexed. @prev holds the make from the previous row
  • The outer query selects data from indexed where the row number is less than 10

Here's the test code, with edge cases of 1 bmw, 3 gmc and 13 fords:

create table cars (id int not null primary key auto_increment, title text, make text, year text);
insert into cars (title, make, year) values 
('f1', 'ford', 2000), ('f2', 'ford', 2001), ('f3', 'ford', 2002), ('f4', 'ford', 2003),
('f5', 'ford', 2004), ('f6', 'ford', 2005), ('f7', 'ford', 2006), ('f8', 'ford', 2007),
('f9', 'ford', 2008), ('f10', 'ford', 2009), ('f11', 'ford', 2010), ('f12', 'ford', 2011),
('f13', 'ford', 2012), ('g1', 'gmc', 2000), ('g2', 'gmc', 2001), ('g3', 'gmc', 2002), 
('b1', 'bmw', 2002);

Output from above query:

+------+----+-------+------+
| make | id | title | year |
+------+----+-------+------+
| bmw  | 17 | b1    | 2002 |
| ford |  1 | f1    | 2000 |
| ford |  2 | f2    | 2001 |
| ford |  3 | f3    | 2002 |
| ford |  4 | f4    | 2003 |
| ford |  5 | f5    | 2004 |
| ford |  6 | f6    | 2005 |
| ford |  7 | f7    | 2006 |
| ford |  8 | f8    | 2007 |
| ford |  9 | f9    | 2008 |
| ford | 10 | f10   | 2009 |
| gmc  | 14 | g1    | 2000 |
| gmc  | 15 | g2    | 2001 |
| gmc  | 16 | g3    | 2002 |
+------+----+-------+------+


It seems that you can do it using stored procedure and cursors. See http://dev.mysql.com/doc/refman/5.0/en/cursors.html for more info

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜