Mysql
 sql >> Base de données >  >> RDS >> Mysql

Additionnez les résultats de quelques requêtes, puis trouvez le top 5 en SQL

Vers UNION les lignes résultantes des trois requêtes, puis choisissez les 5 lignes avec le amount le plus élevé :

(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;

Le manuel :

UNION ALL pour conserver les doublons.

Pour ajouter les décomptes pour chaque 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 partie délicate ici est que tous les event_id sera présent dans les trois requêtes de base. Veillez donc à ce qu'un JOIN ne perd pas complètement les lignes et les ajouts ne s'avèrent pas NULL .

Utilisez UNION ALL , pas UNION . Vous ne voulez pas supprimer des lignes identiques, vous voulez les additionner.

x est un alias de table et un raccourci pour AS x . Il est nécessaire qu'une sous-requête ait un nom. Peut être n'importe quel autre nom ici.

La fonctionnalité SOL FULL OUTER JOIN n'est pas implémenté dans MySQL (la dernière fois que j'ai vérifié), vous devez donc vous contenter de UNION . FULL OUTER JOIN rejoindrait les trois requêtes de base sans perdre de lignes.

Réponse à la question complémentaire

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;

Ou, pour utiliser les décomptes de base de plusieurs manières :

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;