2011-01-14 43 views
4

可以说我有SQL记录:MySQL的选择N记录在GROUP BY基地

 
Country | Number 
USA | 300 
USA | 450 
USA | 500 
USA | 100 
UK | 300 
UK | 400 
UK | 1000 

而且我在做这样的事情:SELECT * FROM table GROUP BY Country
如果我想选择在每个国家/地区仅显示2个最大数字的结果?我怎样才能存档这个?

其结果将是:

 
Country | Number 
USA | 450 
USA | 500 
UK | 400 
UK | 1000 
+0

还,如果你在第二个位置有重复的“数量”值......你只需要在这个速度的一个数字实例? – DRapp 2011-01-14 13:56:54

回答

1

由于MySQL不具有一个内置的RANK函数,查询可能会很慢:

SET @cRank = 0; 
SET @cCoutnry = ''; 

SELECT Country, Number 
FROM (
    SELECT Number, @cRank := IF(@cCoutnry = Country, @cRank+1, 1) AS rank, @cCoutnry := Country Country 
    FROM table 
    ORDER BY Country, Number DESC 
) rs 
WHERE rank < 3 
+0

除了使用表中的每一行之外,你还有更好的选择吗? – ajreal 2011-01-14 07:58:01

+0

@ajreal无法想到更快的任何事情,你可以试着用一个子查询来做这件事,这个子查询将返回最大值,并且在主查询中WHERE数字 2011-01-14 08:05:32

0

让命名表TNAME,那么他们的查询将是。

SELECT * FROM (SELECT ROW_NUMBER() OVER (PARTITION BY X.Country) AS RowNo, * 
FROM (SELECT Country, Name FROM TName ORDER BY Country, Number) X) Y WHERE Y.RowNo <= 2 
2

的样本数据

create table data (Country varchar(10), Number int); 
insert into data select 
'USA' , 300 union all select 
'USA' , 450 union all select 
'USA' , 500 union all select 
'USA' , 100 union all select 
'FR' , 100 union all select 
'FR' , 420 union all select 
'UK' , 300 union all select 
'UK' , 400 union all select 
'UK' , 1000; 

第一种选择是使用像Scrum的梅斯特变量伪排名显示,但这里作为一个单独的语句

SELECT Country, Number 
FROM (
    SELECT 
     Number, 
     @r := case when @c=country then @r+1 else 1 end rownum, 
     @c := Country Country 
    FROM (select @r :=0 , @c := '') x, data 
    ORDER BY Country, Number DESC 
) y 
WHERE rownum < 3; 

如果您正在使用这在前端,只需要2个计数,那么你可以使用这个表格返回一个列表中的计数(单列)

SELECT 
    Country, 
    left(x,locate(',',concat(x,','),locate(',',x)+1)-1) Numbers 
FROM (
    SELECT 
     a.Country, 
     Group_Concat(a.Number) x 
    From (
     select country, number 
     from data 
     order by country, number desc) a 
    group by a.Country 
) b 

结果是

"Country";"Numbers" 
"FR";"420,100" 
"UK";"1000,400" 
"USA";"500,450" 

如果有可能发生联系,则第二形式的该变型中删除关系并示出了“每个国家顶部2个不同的数字”,作为记录。

SELECT distinct x.Country, x.Number 
From data x 
inner join 
(
    SELECT 
     Country, 
     left(x,locate(',',concat(x,','),locate(',',x)+1)-1) Numbers 
    FROM (
     SELECT 
      a.Country, 
      Group_Concat(a.Number) x 
     From (
      select distinct country, number 
      from data 
      order by country, number desc) a 
     group by a.Country 
    ) b 
) y on x.Country=y.Country 
    and concat(',',y.Numbers,',') like concat('%,',x.Number,',%') 
order by x.Country, x.Number Desc 

结果

"Country";"Number" 
"FR";"420" 
"FR";"100" 
"UK";"1000" 
"UK";"400" 
"USA";"500" 
"USA";"450"