sql >> Base de Datos >  >> RDS >> Mysql

Sume los resultados de algunas consultas y luego encuentre los 5 principales en SQL

A UNION las filas resultantes de las tres consultas y luego elija las 5 filas con la amount más alta :

(SELECT event_id, count(*) AS amount
FROM   pageview 
GROUP  BY event_id
ORDER  BY pageviews DESC, rand()
LIMIT  1000)

UNION ALL
(SELECT event_id, count(*)
FROM   upvote
GROUP  BY event_id
ORDER  BY upvotes DESC, rand()
LIMIT  1000)

UNION ALL
(SELECT event_id, count(*)
FROM   attending
GROUP  BY event_id
ORDER  BY attendants DESC, rand()
LIMIT  1000)

ORDER  BY 2 DESC
LIMIT  5;

El manual:

UNION ALL para mantener duplicados.

Para añadir los recuentos de cada event_id :

SELECT event_id, sum(amount) AS total
FROM (
   (SELECT event_id, count(*) AS amount
    FROM   pageview 
    GROUP  BY event_id
    ORDER  BY pageviews DESC, rand()
    LIMIT  1000)
    
    UNION ALL
    (SELECT event_id, count(*)
    FROM   upvote
    GROUP  BY event_id
    ORDER  BY upvotes DESC, rand()
    LIMIT  1000)
    
    UNION ALL
    (SELECT event_id, count(*)
    FROM   attending
    GROUP  BY event_id
    ORDER  BY attendants DESC, rand()
    LIMIT  1000)
    ) x
GROUP  BY 1
ORDER  BY sum(amount) DESC
LIMIT  5;

La parte complicada aquí es que no todos los event_id estará presente en las tres consultas base. Así que tenga cuidado de que un JOIN no pierde filas por completo y las adiciones no resultan NULL .

Usa UNION ALL , no UNION . No desea eliminar filas idénticas, desea agregarlas.

x es un alias de tabla y abreviatura de AS x . Es necesario que una subconsulta tenga un nombre. Puede ser cualquier otro nombre aquí.

La función SOL FULL OUTER JOIN no está implementado en MySQL (la última vez que lo comprobé), así que tienes que conformarte con UNION . FULL OUTER JOIN uniría las tres consultas base sin perder filas.

Respuesta a la pregunta de seguimiento

SELECT event_id, sum(amount) AS total
FROM (
   (SELECT event_id, count(*) / 100 AS amount
    FROM   pageview ... )
    
    UNION ALL
    (SELECT event_id, count(*) * 5 
    FROM   upvote ... )
    
    UNION ALL
    (SELECT event_id, count(*) * 10
    FROM   attending ... )
    ) x
GROUP  BY 1
ORDER  BY  sum(amount) DESC
LIMIT  5;

O bien, para utilizar los recuentos básicos de varias formas:

SELECT event_id
      ,sum(CASE source
              WHEN 'p' THEN amount / 100
              WHEN 'u' THEN amount * 5
              WHEN 'a' THEN amount * 10
              ELSE 0
           END)  AS total
FROM (
   (SELECT event_id, 'p'::text AS source, count(*) AS amount
    FROM   pageview ... )
    
    UNION ALL
    (SELECT event_id, 'u'::text, count(*)
    FROM   upvote ... )
    
    UNION ALL
    (SELECT event_id, 'a'::text, count(*)
    FROM   attending ... )
    ) x
GROUP  BY 1
ORDER  BY 2 DESC
LIMIT  5;