SQL如何选择受一列限制的最新记录

时间:2011-02-05 21:38:34

标签: sql mysql

有一个MySql数据库看起来像这样:

Id / name / hobby / province / created - int8

我想为每个省份只选择三条记录,但我不知道如何......

所以结果应该看起来像这样

[province1]

[1] blah bla

[2] blah blah

[3] blah blah

[province2]

[1] blah bla

[2] blah blah

[3] blah blah

感谢您的帮助。 最好的祝福。 微米。

4 个答案:

答案 0 :(得分:1)

我不认为一个查询可以完成,除非您的数据库很小,因此您可以在脚本中进行进一步过滤。

  • 首先,找出你所拥有的省份:SELECT DISTINCT province FROM t
  • 为每个省运行单独的查询,按“创建的DESC”和LIMIT 3对其进行排序。
  • 确保将“省”和“已创建”编入索引。

答案 1 :(得分:1)

SELECT * FROM
(
     SELECT t1.*, @num := IF(@t1 = province,@num+1,1) as num_in_group, @t1 := province
     FROM table_name t1
     INNER JOIN (SELECT @num:=0) num_table
     ORDER BY province ASC, id desc
)xxx WHERE num_in_group <=3

这是非常直接且不是非常有效的方法,但从一开始可能会有所帮助。

<强>更新

SELECT * FROM
(
     SELECT t1.*, @num := IF(@t1 = province,@num+1,1) as num_in_group, @t1 := province
     FROM table_name t1
     INNER JOIN (SELECT @num:=0) num_table
     INNER JOIN (SELECT @t1 := NULL)x1
     ORDER BY province ASC, id desc
)xxx WHERE num_in_group <=3

答案 2 :(得分:1)

在支持row_number()的数据库中,“每组前N个”问题很容易,但MySQL并不是其中之一。据我所知,只有相当丑陋的解决方法。一种方法是group_concat方式:

select  yt.province
,       lst.value
,       substring_index(
            substring_index(
                group_concat(name separator ';'),
                ';',lst.value),
            ';',-1)
from    YourTable yt
cross join
        (
        select 1 as value
        union all select 2
        union all select 3
        ) lst
group by
    yt.Province
,       lst.value;

如果每个省的名称少于三个,则会返回重复的行。你可以用另一个子查询排除那些。

另一种方法是变量方式,由Alex发布(我投票赞成)。格式略有不同:

select  *
from    (
        SELECT  name
        ,       province
        ,       @num := if(@lastprov = province,@num+1,1) as num_in_group
        ,       @lastprov := province
        from    YourTable yt
        order by
                province
        ) as SubQueryAlias
JOIN    (SELECT @num:=0, @lastprov:=null) as DeclareVariablesSubquery
WHERE   num_in_group <= 3;

测试数据:

drop table if exists YourTable;

create table YourTable (id int, name varchar(25), province varchar(25));
insert YourTable values 
    (1,'Barack','New York'), 
    (2,'George W','New York'),
    (3,'William','New York'),
    (4,'George HW','New York'),
    (5,'Ronald','Texas'),
    (6,'James','Texas'),
    (7,'Gerald','Texas'),
    (8,'Richard','Texas'),
    (9,'Lyndon','California'),
    (10,'John','California'),
    (11,'Dwight','Rhode Island'),
    (12,'Harry','Wisconsin');

答案 3 :(得分:0)

这对MySQL不起作用(这就是为什么我将这个答案标记为社区维基),但是对于使用不同DBMS的人来说这很有趣并且绊倒了这个问题:

WITH TT (id, province, R) AS (
    SELECT id, province, row_number() OVER(PARTITION BY province ORDER BY id DESC)
      FROM your_table
  GROUP BY id, province
)
SELECT id, province
  FROM TT
 WHERE R <= 3;