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_ID
ADDED
无论如何,我们正在推动 MySQL 应该做的事情,并创建一个潜在的巨大内存表 ( P
),以便在每个表中提取几行OWNER_ID
,所以这既不美观也不推荐。LIMIT
尽管如此,据我所知,在 MySQL 开始支持子查询中的分析函数或子句之前,这已经是最好的了。
工作小提琴