选择ID在何处(ID列表),并限制MySQL中每个ID的记录

选择ID在何处(ID列表),并限制MySQL中每个ID的记录,mysql,sql,Mysql,Sql,我遇到了一种情况,我有一个存储表的ID列表,需要从每个存储中获取最新的10个文件 SELECT * FROM tblFiles WHERE storeId in (IDs) ORDER BY createdDate DESC LIMIT 10 但是,这限制了整个结果。我找到了一个类似问题的答案。但是,答案建议对每个ID使用循环。这会导致多个DB命中 另一个选项是获取所有记录并在代码中对它们进行分组。但是,如果有大量的记录,这将是沉重的 如果可以在查询级别处理,那就太好了。任何帮助都将

我遇到了一种情况,我有一个存储表的ID列表,需要从每个存储中获取最新的10个文件

SELECT * 
FROM tblFiles 
WHERE storeId in (IDs) 
ORDER BY createdDate DESC  
LIMIT 10
但是,这限制了整个结果。我找到了一个类似问题的答案。但是,答案建议对每个ID使用循环。这会导致多个DB命中

另一个选项是获取所有记录并在代码中对它们进行分组。但是,如果有大量的记录,这将是沉重的

如果可以在查询级别处理,那就太好了。任何帮助都将不胜感激


注意:此处使用的表是虚拟表。

您可以使用联合查询解决此问题,其中每个子查询搜索特定id并强制执行LIMIT子句,如:

(SELECT * 
FROM tblFiles
WHERE storeId = ?
ORDER BY createdDate DESC
LIMIT 10)
UNION
(SELECT * 
FROM tblFiles
WHERE storeId = ?
ORDER BY createdDate DESC
LIMIT 10)
...
使用此解决方案,只会发生一次db命中,并且您可以保证在每个id的基础上获得限制。这样的SQL可以很容易地从php代码中生成

注意:mysql查询中允许的最大联合数为61。

在where中使用select

SELECT * from tblFiles where storeId in (SELECT id from store ORDER BY datefield/id field desc limit 10)

在MySQL 8.0之前,最简单的方法可能是变量:

select f.*
from (select f.*,
             (@rn := if(@s = storeId, @rn + 1,
                        if(@s := storeId, 1, 1)
                       )
             ) as rn
      from (select f.*
            from tblfiles f
            where storeId in (IDs) 
            order by storeId, createdDate desc
           ) f cross join
           (select @s := 0, @rn := 0) params
     ) f
where rn <= 10;
在MySQL 8+或MariaDB 10.3+中,您只需使用窗口函数:

select f.*
from (select f.*,
             row_number() over (partition by storeid order by createdDate desc) as seqnum
      from tblfiles f
     ) f
where seqnum <= 10;

在较旧版本的MySQL和MariaDB中,可能不需要最里面的子查询。

您使用的是哪个版本的MySQL?MySQL版本5.6.28检查此版本很好。但是,如果请求中有更多的ID storeId,则查询将变为一个大查询。@Abhishek:61 UNIONs是最大值。查询很大,但很容易动态生成……这个很好。我认为你必须在最后一个where子句中使用rn而不是@rn。@Abhishek。对我几乎可以肯定联合查询会比使用变量更快,虽然没有那么优雅。