У базі даних 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)
);
Поки я намагався скинути ідентифікатор публікації та загальну вагу в подання, а потім приєднав цей погляд до себе, щоб отримати сукупний підрахунок:
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 хвилин без закінчення, чого я не можу зробити у виробництві.
Чи є більш ефективний спосіб зробити це?
Якщо ви зацікавлені в тестуванні всього набору даних, його можна завантажити тут . Файл становить близько 60 Мб, він розширюється приблизно до 250 Мб. З іншого боку , є 12000 рядків по суті GitHub тут .
w.weight
- правда? Я хочу підрахувати пости із загальною вагою (сума ваг їх відповідних рядків причин) ltew.weight
.