寻找限制SQL的方法每个特定列产生3个结果

时间:2010-02-22 20:30:40

标签: sql mysql union limit

我有一个包含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上找到了答案,我发现了类似的问题,但没有任何问题与我遇到的问题相符。有什么想法吗?

4 个答案:

答案 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 / TimeStampASCDESC排序) 如果表格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

...