1

我有一个表,它计算不同用户在不同对象上发生的一个特定操作:

CREATE TABLE `Actions` (
    `object_id` int(10) unsigned NOT NULL,
    `user_id` int(10) unsigned NOT NULL,
    `actionTime` datetime
);

每次用户执行此操作时,都会插入一行。我可以计算对每个对象执行了多少操作,并按“活动”对对象进行排序:

SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
ORDER BY action_count;

如何将结果限制为前 n 个对象?LIMIT 子句在聚合之前应用,因此会导致错误的结果。该表可能很大(数百万行),我可能需要每分钟计算数十次,所以我想尽可能高效地执行此操作。

编辑:实际上,机器是对的,而我在应用 LIMIT 的时间上是错误的。我的查询返回了正确的结果,但是将它们呈现给我的 GUI 让我失望了……这让这个问题变得毫无意义。对不起!

4

4 回答 4

2

实际上... LIMIT 最后应用,在最终的 HAVING 子句之后。所以它不应该给你不正确的结果。但是,由于 LIMIT 是最后应用的,它不会提供更快的查询执行速度,因为在截断结果之前,必须创建一个临时表并按照操作计数的顺序进行排序。另外,请记住按降序排序:

SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
ORDER BY action_count DESC
LIMIT 10;

您可以尝试向 object_id 添加索引以进行优化。这样,只需要扫描索引而不是Actions表。

于 2009-05-26T20:26:37.687 回答
1

我知道这个线程已有 2 年历史,但 stackflow 仍然认为它是相关的,所以这里是我的 0.02 美元。ORDER BY 子句在计算上非常昂贵,因此在大型表中应避免使用它们。我使用的一个技巧(部分来自 Joe Celko 为 Smarties 编写的 SQL)类似于:

SELECT COUNT(*) AS counter, t0.object_id FROM (SELECT COUNT(*), actions.object_id FROM actions GROUP BY id) AS t0, (SELECT COUNT(*), actions.object_id FROM actions GROUP BY id) AS t1 WHERE t0.object_id < t1.object_id  GROUP BY object_id HAVING counter < 15

将为您提供前 15 个编辑过的对象,无需排序。请注意,从 v5 开始,mysql 只会缓存完全重复(包括空格)查询的结果集,因此不会缓存嵌套查询。使用视图可以解决这个问题。

是的,它是三个查询而不是两个,唯一的好处是不必对分组查询进行排序,但如果你有很多组,它会更快。

旁注:查询对于没有排序的中值函数非常方便

于 2011-03-03T00:47:12.783 回答
1

怎么样:

SELECT * FROM
(
SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
ORDER BY action_count
)
LIMIT 15

此外,如果您对必须包含的最小操作数有一定的衡量标准(例如,前 n 个肯定超过 1000 个),您可以通过添加 HAVING 子句来提高效率:

SELECT * FROM
(
SELECT object_id, count(object_id) AS action_count 
FROM `Actions` 
GROUP BY object_id 
HAVING action_count > 1000
ORDER BY action_count
)
LIMIT 15
于 2009-05-26T20:20:46.297 回答
0
SELECT * FROM (SELECT object_id, count(object_id) AS action_count 
        FROM `Actions` 
        GROUP BY object_id 
        ORDER BY action_count) LIMIT 10;
于 2009-05-26T20:20:44.673 回答