MySQL 在有序选择中选择前 3 行

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6218233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 20:06:56  来源:igfitidea点击:

selecting top 3 rows in an ordered select

mysqlsql-order-bylimitgreatest-n-per-group

提问by mike_haney

i have table data like this:

我有这样的表数据:

id,time,otherdata
a,1,fsdfas
a,2,fasdfag
a,3,fasdfas
a,7,asfdsaf
b,8,fasdf
a,8,asdfasd
a,9,afsadfa
b,10,fasdf
...

so essentially, i can select all the data in the order i want by saying something like:

所以本质上,我可以通过说以下内容按我想要的顺序选择所有数据:

select * from mytable ordered by id,time;

so i get all the records in the order i want, sorted by id first, and then by time. but instead of getting all the records, i need the latest 3 times for each id.

所以我按照我想要的顺序获取所有记录,首先按 id 排序,然后按时间排序。但不是获取所有记录,我需要每个 id 的最新 3 次。

Answer:

回答:

Well, I figured out how to do it. I'm surprised at how quick it was, as I'm operating on a couple million rows of data and it took about 11 seconds. I wrote a procedure in a sql script to do it, and here's what it looks like. --Note that instead of getting the last 3, it gets the last "n" number of rows of data.

嗯,我想出了怎么做。我很惊讶它的速度有多快,因为我正在处理几百万行数据,大约需要 11 秒。我在 sql 脚本中编写了一个程序来执行此操作,这就是它的样子。-- 请注意,它不是获取最后 3 行,而是获取最后“n”行数据。

use my_database;

drop procedure if exists getLastN;
drop table if exists lastN;

-- Create a procedure that gets the last three records for each id
delimiter //
create procedure getLastN(n int)
begin
  # Declare cursor for data iterations, and variables for storage
  declare idData varchar(32);
  declare done int default 0;
  declare curs cursor for select distinct id from my_table;
  declare continue handler for not found set done = 1;
  open curs;

  # Create a temporary table to contain our results
  create temporary table lastN like my_table;

  # Iterate through each id
  DATA_LOOP: loop

  if done then leave DATA_LOOP; end if;
  fetch curs into idData;
  insert into lastThree select * from my_table where id = idData order by time desc limit n;

  end loop;
end//

delimiter ;
call getLastN(3);
select * from lastN;

sorry if this doesn't exactly work, I've had to change variable names and stuff to obfuscate my work's work, but i ran this exact piece of code and got what i needed!

对不起,如果这不完全有效,我不得不更改变量名称和内容来混淆我的工作,但我运行了这段代码并得到了我需要的东西!

回答by Halcyon

I think it's as simple as:

我认为这很简单:

SELECT * FROM `mytable`
GROUP BY `id`
ORDER BY `time` DESC
LIMIT 3

回答by wwkudu

Two approaches that I'm aware of are (1) to use a set of unions, each one containing a "limit 3", or (2) to use a temporary variable. These approaches, along with other useful links and discussion can be found here.

我知道的两种方法是 (1) 使用一组联合,每个联合都包含“限制 3”,或 (2) 使用临时变量。这些方法以及其他有用的链接和讨论可以在这里找到。

回答by pSub

Try this:

尝试这个:

select *
from mytable as m1
where (
   select count(*) from mytable as m2
   where m1.id = m2.id
) <= 3 ORDER BY id, time