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