Mysql
 sql >> Database >  >> RDS >> Mysql

Somma i risultati di alcune query e quindi trova i primi 5 in SQL

A UNION le righe risultanti di tutte e tre le query, quindi scegli le 5 righe con il amount più alto :

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

Il manuale:

UNION ALL per conservare i duplicati.

Per aggiungere i conteggi per ogni 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 difficile qui è che non tutti gli event_id sarà presente in tutte e tre le query di base. Quindi assicurati che un JOIN non perde completamente le righe e le aggiunte non risultano NULL .

Usa UNION ALL , non UNION . Non vuoi rimuovere righe identiche, vuoi aggiungerle.

x è un alias di tabella e una scorciatoia per AS x . È necessario che una sottoquery abbia un nome. Può essere qualsiasi altro nome qui.

La funzione SOL FULL OUTER JOIN non è implementato in MySQL (l'ultima volta che ho controllato), quindi devi accontentarti di UNION . FULL OUTER JOIN unirebbe tutte e tre le query di base senza perdere righe.

Rispondi alla domanda di follow-up

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;

Oppure, per utilizzare i conteggi di base in più modi:

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;