SELECT *
FROM
(
SELECT
P2.ID,
IF (@PREVIOUS_OWNER = P2.OWNER_ID,
@CURRANK := @CURRANK + 1,
@CURRANK := 1) AS RANK,
(@PREVIOUS_OWNER := P2.OWNER_ID) AS OWNER_ID,
P2.ADDED
FROM PRODUCTS P2, (SELECT @CURRANK := -1, @PREVIOUS_OWNER := -1) R
ORDER BY P2.OWNER_ID, P2.ADDED DESC
) P
WHERE P.RANK <= 2
这个查询在做什么?
- 它根据
owner_id和对结果进行排序date
- 它声明了两个变量
CURRANK和PREVIOUS_OWNER
PREVIOUS_OWNER将在计算OWNER_ID 后被 CURRANK评估为当前,这意味着IF语句内部的第一行将PREVIOUS_OWNER是-1,而前一行 OWNER_ID是每隔一行
- 最后但同样重要的是,如果 与
PREVIOUS_OWNER当前相同,OWNER_ID则我们递增CURRANK,否则我们将其重置为 1(if 子句),以便我们可以通过以下方式模拟分区OWNER_ID
因此,内部查询将根据 对来自同一所有者的每个产品进行排名ADDED。秩别名为RANK。
外部查询过滤RANK小于或等于 2。
这是有点放克的代码,但如果您为andCOUNT(*)创建索引,它的性能应该比对应的更好。OWNER_IDADDED
无论如何,我们正在推动 MySQL 应该做的事情,并创建一个潜在的巨大内存表 ( P),以便在每个表中提取几行OWNER_ID,所以这既不美观也不推荐。LIMIT尽管如此,据我所知,在 MySQL 开始支持子查询中的分析函数或子句之前,这已经是最好的了。
工作小提琴