我有一个包含9个用户ID的列表,并希望为每个用户ID选择3个条目。
我当前的查询是这样的。
SELECT * FROM entries WHERE user_id IN (1,2,3,4,5,6,7,8,9) LIMIT 27
有些用户有超过3个条目,所以我想将此查询的结果限制为每个用户3个条目。
我尝试制作一个9个单独查询的UNION,其中每个查询都有自己的限制3,但这在服务器上非常慢。
我已经在SO上找到了答案,我发现了类似的问题,但没有任何问题与我遇到的问题相符。有什么想法吗?
答案 0 :(得分:2)
假设表entries
有另一列id
作为其唯一标识符,则后续查询应该有效(未经测试):
SELECT e.*
FROM entries e
INNER JOIN (SELECT e.id
FROM entries e
INNER JOIN entries x
ON e.user_id = x.user_id
--// define the field (ID, TimeStamp) here to specify which top 3,
--// and use sign to specify ASC/DESC (<=, >=)
AND e.id <= x.id
GROUP BY e.id
HAVING COUNT(*) <= 3 --//only top 3
) f
ON e.id = f.id
使用此查询,您还可以定义要查看的3行(按ID
/ TimeStamp
,ASC
或DESC
排序)
如果表格entries
只有几列,您可以GROUP BY
表格中的所有列,并避免使用sub-select
。
答案 1 :(得分:0)
如果您只是选择3个随机条目,那么UNION可能是最好的方法。
我发现很难相信一个简单的UNION在服务器上“非常慢”,除非你有一个索引不好的表,或者正在选择一些巨大的列。你真的需要SELECT *
吗?可能不是。
请使用SHOW CREATE TABLE entries\G
以及EXPLAIN SELECT ... UNION ... \G
答案 2 :(得分:0)
您可以使用auto_increment列作为复合键的最后一个组件,以充当与键的其他组件匹配的值的计数器。
EG。
create temporary table temptab ( userid int not null,
rank int auto_increment not null,
primary key (userid, rank ) );
insert into temptab select userid, NULL from entries order by userid;
# change the "order by" to fit your criteria - eg. order by last_used desc, ...
delete from temptab where rank > 3;
select * from temptab order by userid, rank;
应该返回:
1, 1
1, 2
1, 3
2, 1
...
这需要调整以适合您的使用。可能还会将条目表中的主键插入临时表,以便从temptab到条目的连接可以生成一些有用的数据。
答案 3 :(得分:-1)
尝试以下
SELECT TOP 3 * FROM entries
WHERE user_id = 1
UNION ALL
SELECT TOP 3 * FROM entries
WHERE user_id = 2
UNION ALL
...