将OFFSET和LIMIT分别应用于结果的子部分

时间:2015-04-15 14:37:51

标签: mysql limit

这是我在这里发表的第一篇文章,如果我打破协议,请道歉。

我有一个单独的表,为了参数我将调用t1,表格如下:

id -- primary key
fk_id -- foreign key
date_created

我有一组来自先前查询的fk_id。

这是一个完全返回我想要的查询,但使用UNION,对于我可能需要搜索的数百甚至数千个fk_id来说效率非常低:

  SELECT *
    FROM t1
   WHERE fk_id = ?
ORDER BY date_created DESC
   LIMIT m, n
UNION
  SELECT *
    FROM t1
   WHERE fk_id = ?
ORDER BY date_created DESC
   LIMIT m, n
UNION -- ... for each fk_id

请注意,每个UNION的偏移量和限制值m和n都相同。

我想要的是一个不使用UNION的查询,而是说

之类的内容
WHERE fk_id IN (?, ?, ?, ...)

但保留LIMIT对每个子集的单独应用。

1 个答案:

答案 0 :(得分:0)

您需要为每个fk分配一个行号。最好的方法可能是使用变量:

SELECT t.*
FROM (SELECT t1.*,
             (@rn := if(@f = fk_id, @rn + 1,
                        if(@f := fk_id, 1, 1)
                       )
             ) rn
      FROM t1 CROSS JOIN
           (SELECT @f := -1, @rn := 0) vars
      ORDER BY fk_id, date_created DESC
     ) t
WHERE rn >= m and rn < m + n;

编辑:

如果只有MySQL支持以下(几乎)ANSI语法,那么这可能会更有效:

select t1.*
from t1
where t1.id in (select id
                from t1 tt1
                where tt1.fk_id = t1.fk_id
                order by date_created desc
                limit m, n
               );

我不是百分百肯定,但这应该利用t1(fk_id, date_created)t1(id)上的索引。如果它使用这些索引,那么它应该可以很好地工作。