我需要在表格中为每个符合一系列标准的用户返回最新的2行。
例如,“从产品表中获取最新的2行,用户状态未挂起的用户,并且用户注册的时间超过一周”。
我不完全确定从哪里开始。如果每个用户只有一行就很简单。同样,如果我可以将结果转储出来并在我的PHP代码中进行进一步过滤,我可以通过这种方式使其工作(但是我需要LIMIT分页,所以它需要全部在查询中)。
我已经设置了一个非常简化的表格,其中包含一些数据,只是为了便于处理,您可以在此处看到:
http://sqlfiddle.com/#!2/b32d2
基本上,解决方案查询每个“owner_id”最多返回两行,返回的两行将是“添加”列中最高的2个日期。
希望这是有道理的,并感谢任何可以提供帮助的人。
答案 0 :(得分:3)
这是非常低效的,但它确实有效。
SELECT * FROM `products` p1
WHERE (SELECT COUNT(*)
FROM `products` p2
WHERE p2.added > p1.added
AND p2.owner_id = p1.owner_id
) < 2
答案 1 :(得分:0)
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.
这是一种有趣的代码,但如果为COUNT(*)
和OWNER_ID
创建索引,则可能会比ADDED
代码更好。
无论如何,我们正在推动MySQL应该做的事情的边缘,并创建一个潜在巨大的内存表(P
),以便每OWNER_ID
提取几行,所以这不是美丽也不推荐。尽管如此,据我所知,在MySQL开始支持子查询中的分析函数或LIMIT
子句之前,这是一样好的。