[英]mySQL - select the top n rows, grouped by 2 columns
I've found existing questions with the latest/lowest single row over several fields, or latest n rows over a single field, but not the two together 我已经找到了现有的问题,包括几个字段的最新/最低单行,或单个字段上的最新n行,但不是两个在一起
I need to construct 2 queries, using this example table (similar to this question ) 我需要构建2个查询,使用此示例表(类似于此问题 )
CREATE TABLElap_data
(id
int(1) NOT NULL,track_id
int(1) NOT NULL,user_id
int(1) NOT NULL,lap_time
time NOT NULL,lap_status
tinyint(1) NOT NULL, PRIMARY KEY (id
) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
INSERT INTO `lap_data` (`id`, `track_id`, `user_id`, `lap_time`, `lap_status`) VALUES (1, 1, 1, '04:18:23', 1), (2, 2, 2, '01:09:54', 1), (3, 2, 1, '01:05:30', 1), (4, 1, 2, '04:17:02', 1), (5, 3, 2, '01:13:10', 1), (6, 4, 1, '01:36:59', 0), (7, 3, 2, '01:18:10', 1), (8, 2, 3, '01:06:42', 1), (9, 1, 1, '04:16:12', 1), (10, 1, 2, '04:18:12', 1), (11, 2, 3, '01:03:20', 1), (12, 2, 1, '01:08:13', 1), (13, 2, 1, '01:09:44', 1), (14, 3, 2, '01:14:10', 1), (15, 3, 2, '01:17:20', 1), (16, 4, 1, '01:36:23', 1), (17, 2, 1, '01:11:34', 1);
Query 1: 查询1:
This is the query I've been using elsewhere to collect the two latest records of a given type, which is the closest to what I think I need, modified to this example .. although unfinished, as in the other instance, it was only collecting the 2 most recent rows for each user_id .. here I need it to take track_id into account as well 这是我在其他地方用来收集给定类型的两个最新记录的查询,这个记录最接近我认为我需要的,修改为这个例子..虽然未完成,但在另一个例子中,它只是收集每个user_id的2个最新行..在这里我需要它也考虑到track_id
SELECT
*
FROM (
SELECT
t.id,
t.track_id,
t.user_id,
t.lap_time,
t.lap_status,
@row:=case WHEN @prev=user_id THEN @row ELSE 0 END +1 rn,
@prev:=user_id
FROM `lap_data` t
CROSS JOIN (SELECT @row:=0, @prev:=null) c
WHERE t.user_id IN (1,2)
ORDER BY user_id, id DESC
) src
WHERE rn <= 2
ORDER BY lap_time DESC
Query 1 Desired result: ( WHERE user_id IN (1,2) ) 查询1所需结果: (WHERE user_id IN(1,2))
| id | track_id | user_id | lap_time | lap_status | -------------------------------------------------------------- | 9 | 1 | 1 | 04:16:12 | 1 | | 1 | 1 | 1 | 04:18:23 | 1 | | 3 | 2 | 1 | 01:05:30 | 1 | | 12 | 2 | 1 | 01:08:13 | 1 | | 16 | 4 | 1 | 01:36:23 | 1 | | 6 | 4 | 1 | 01:36:59 | 1 | | 4 | 1 | 2 | 04:17:02 | 1 | | 10 | 1 | 2 | 04:18:12 | 1 | | 2 | 2 | 2 | 01:09:54 | 1 | | 5 | 3 | 2 | 01:13:10 | 1 | | 14 | 3 | 2 | 01:14:10 | 1 |
Query 2: 查询2:
Query 2 Desired result: ( WHERE user_id = '1' ) 查询2所需结果: (WHERE user_id ='1')
| id | track_id | user_id | lap_time | lap_status | -------------------------------------------------------------- | 13 | 2 | 1 | 01:09:44 | 1 | | 17 | 2 | 1 | 01:11:34 | 1 |
Any suggestions? 有什么建议么? thanks! 谢谢!
MYSQL Version for my previous answer: 我之前回答的MYSQL版本:
SELECT
lt.id,
lt.user_id,
lt.track_id,
lt.lap_status,
lt.lap_time
FROM (
SELECT id,
user_id,
track_id,
lap_status,
lap_time,
CASE WHEN track_id = @prevTrackId AND user_id = @prevUserId THEN @curRank := @curRank + 1 ELSE @curRank := 1 END Rank,
@prevTrackId := track_id,
@prevUserId := user_id
FROM lap_data, (SELECT @curRank := 0, @prevTrackId := 1, @prevUserId := 1) r
ORDER BY user_id,track_id,lap_time ASC
) lt
WHERE Rank <= 2
This query makes one important (and quite likely erroneous) assumption - which is that the highest track_id of the previous user is higher than (or at least different from) the lowest track_id of the following user. 该查询产生一个重要的(并且很可能是错误的)假设 - 即先前用户的最高track_id高于(或至少不同)后续用户的最低track_id。
If that's not the case, then you may need to store another variable, or base 'prev' on the concatenation of two values... 如果不是这种情况,那么您可能需要存储另一个变量,或者将“prev”基于两个值的串联...
SELECT x.id
, x.track_id
, x.user_id
, x.lap_time
, x.lap_status
FROM
( SELECT l.*
, CASE WHEN @prev = track_id THEN @i:=@i+1 ELSE @i:=1 END rank
, @prev:=track_id prev
FROM lap_data l
, (SELECT @prev:=null,@i:=0) vars
WHERE user_id IN(1,2)
ORDER
BY user_id
, track_id
, lap_time
) x
WHERE x.rank <=2
ORDER
BY user_id
, track_id
, lap_time;
select id,track_id,user_id,lap_status,lap_time from (
select @rank:=if(@prev_cat=user_id,@rank+1,1) as rank,id,user_id,track_id,lap_status,lap_time,@prev_cat:=user_id
from lap_data,(select @rank:=0, @prev_cat:="")t
where user_id IN(1,2) order by track_id, user_id desc
) temp
where temp.rank<=2
Query 1: 查询1:
SELECT lt.id,lt.user_id,lt.track_id,lt.lap_status,lt.lap_time
FROM (
SELECT id,user_id,track_id,lap_status,lap_time,Rank()
over (Partition BY user_id,track_id
ORDER BY lap_time ASC ) AS Rank
FROM lap_data
WHERE user_id IN (1,2)
) lt WHERE Rank <= 2
Query 2: Simply just select all records which NOT IN
Query 1. (assuming id is the primary key of your table, which you did not even set a primary key for lap_data table) 查询2:只需选择NOT IN
Query 1中的所有记录(假设id是表的主键,你甚至没有为lap_data表设置主键)
SELECT * FROM lap_data
WHERE id NOT IN
(SELECT lt.id
FROM (
SELECT id,Rank()
over (Partition BY user_id,track_id
ORDER BY lap_time ASC ) AS Rank
FROM lap_data
WHERE user_id = 1
) lt WHERE Rank <= 2)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.