我在MySQL 5.7.22数据库中有两个表:posts
和reasons
。每个帖子行都有并且属于许多原因行。每个原因都有一个相关的权重,因此每个帖子都有一个相关的总权重。
对于10个重量点的每个增量(即0、10、20、30等),我希望获得总权重小于或等于该增量的帖子数。我希望这样做的结果看起来像这样:
weight | post_count
--------+------------
0 | 0
10 | 5
20 | 12
30 | 18
... | ...
280 | 20918
290 | 21102
... | ...
1250 | 118005
1260 | 118039
1270 | 118040
总权重大致呈正态分布,有一些非常低的值和一些非常高的值(当前最大值为1277),但大部分位于中间。大约有120,000行posts
,而大约有120 行reasons
。每个帖子平均有5或6个原因。
表格的相关部分如下所示:
CREATE TABLE `posts` (
id BIGINT PRIMARY KEY
);
CREATE TABLE `reasons` (
id BIGINT PRIMARY KEY,
weight INT(11) NOT NULL
);
CREATE TABLE `posts_reasons` (
post_id BIGINT NOT NULL,
reason_id BIGINT NOT NULL,
CONSTRAINT fk_posts_reasons_posts (post_id) REFERENCES posts(id),
CONSTRAINT fk_posts_reasons_reasons (reason_id) REFERENCES reasons(id)
);
到目前为止,我已经尝试将帖子ID和总权重放入视图中,然后将该视图与其自身合并以获取汇总计数:
CREATE VIEW `post_weights` AS (
SELECT
posts.id,
SUM(reasons.weight) AS reason_weight
FROM posts
INNER JOIN posts_reasons ON posts.id = posts_reasons.post_id
INNER JOIN reasons ON posts_reasons.reason_id = reasons.id
GROUP BY posts.id
);
SELECT
FLOOR(p1.reason_weight / 10) AS weight,
COUNT(DISTINCT p2.id) AS cumulative
FROM post_weights AS p1
INNER JOIN post_weights AS p2 ON FLOOR(p2.reason_weight / 10) <= FLOOR(p1.reason_weight / 10)
GROUP BY FLOOR(p1.reason_weight / 10)
ORDER BY FLOOR(p1.reason_weight / 10) ASC;
但是,这是非常缓慢的-我让它运行15分钟而不终止,这在生产中是无法做到的。
有没有更有效的方法可以做到这一点?
如果您有兴趣测试整个数据集,可在此处下载。该文件大约为60MB,可扩展到大约250MB。或者,有12000行的GitHub的要点在这里。
w.weight
-是吗?我希望计算的总重量(其相关原因行的权重之和)为ltew.weight
。