Tengo dos tablas en una base de datos MySQL 5.7.22: posts
y reasons
. Cada fila de publicación tiene y pertenece a muchas filas de razones. Cada razón tiene un peso asociado y, por lo tanto, cada publicación tiene un peso agregado total asociado.
Para cada incremento de 10 puntos de peso (es decir, para 0, 10, 20, 30, etc.), quiero obtener un recuento de publicaciones que tengan un peso total menor o igual a ese incremento. Esperaría que los resultados se vean así:
weight | post_count
--------+------------
0 | 0
10 | 5
20 | 12
30 | 18
... | ...
280 | 20918
290 | 21102
... | ...
1250 | 118005
1260 | 118039
1270 | 118040
Los pesos totales se distribuyen aproximadamente normalmente, con unos valores muy bajos y unos valores muy altos (el máximo es actualmente 1277), pero la mayoría en el medio. Hay poco menos de 120,000 filas posts
y alrededor de 120 pulgadas reasons
. Cada publicación tiene en promedio 5 o 6 razones.
Las partes relevantes de las tablas se ven así:
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)
);
Hasta ahora, he intentado colocar el ID de la publicación y el peso total en una vista, luego unir esa vista para obtener un recuento agregado:
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;
Sin embargo, eso es inusualmente lento: lo dejé correr durante 15 minutos sin terminar, lo que no puedo hacer en producción.
¿Hay una manera más eficiente de hacer esto?
En caso de que esté interesado en probar todo el conjunto de datos, se puede descargar aquí . El archivo tiene alrededor de 60 MB, se expande a alrededor de 250 MB. Alternativamente, hay 12,000 filas en una esencia de GitHub aquí .
w.weight
, ¿es así? Estoy buscando contar publicaciones con un peso total (suma de pesos de sus filas de razón asociadas) de ltew.weight
.