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

SQL如何选择受一列限制的最新记录,sql,mysql,Sql,Mysql,有一个MySql数据库如下所示: Id/姓名/爱好/省份/已创建-int8 我只想为每个省选择三项记录,但我不知道如何 所以结果应该是这样的 [省1] [1] 诸如此类 [2] 废话 [3] 废话 [省2] [1] 诸如此类 [2] 废话 [3] 废话 等等 谢谢你的帮助。 顺致敬意, M.我不认为一个查询就可以完成,除非您的数据库很小,所以您可以在脚本中进行进一步过滤 首先,找出您拥有的省份:从t中选择不同的省份 为每个省份运行单独的查询,按“created DESC”和LIMIT 3进行排序

有一个MySql数据库如下所示:

Id/姓名/爱好/省份/已创建-int8

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

所以结果应该是这样的

[省1]

[1] 诸如此类

[2] 废话

[3] 废话

[省2]

[1] 诸如此类

[2] 废话

[3] 废话

等等

谢谢你的帮助。 顺致敬意,
M.

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

首先,找出您拥有的省份:从t中选择不同的省份 为每个省份运行单独的查询,按“created DESC”和LIMIT 3进行排序。 确保“省”和“已创建”已编入索引。 这是一种非常直接且不是非常有效的方法,但它可能会有所帮助,并且从一开始就很好

更新


这对MySQL不起作用,这就是为什么我将此答案标记为community wiki的原因,但对于使用不同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;

在支持行数的数据库中,每个组前N个问题很容易解决,但MySQL不是其中之一。据我所知,只有相当丑陋的变通办法。其中一种方法是集团合作方式:

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

另一种方法是可变方式,正如我投票支持的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;

在循环中执行查询总是一个糟糕的解决方案。首先,感谢您的帮助。上面的脚本工作得很好,但是我有num_table=1作为所有结果。但是结果排序很好。你能发布你正在使用的查询吗?我很确定我的查询应该可以完成任务。从SELECT t1中选择*。@num:=IF@t1=省,@num+1,1作为\u组中的num\u,@t1:=省从人民t1内部连接选择@num:=0 num\u表顺序按省ASC,id desc xxx,其中\u组中的num\u我可能误解了您。如果您不想在_组中显示额外的@t、num_列,只需在外部查询中列出所有省_表字段名称,而不是选择*。您确定每个省有多个记录吗?谢谢您的投票。我的原始查询中有一个问题,因此您可能需要稍微更改第二种方法。我错过了@lastprov初始化,在第一次执行查询时导致了错误的结果。
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;
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;
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');