Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Summieren Sie die Ergebnisse einiger Abfragen und finden Sie dann die Top 5 in SQL

An UNION die resultierenden Zeilen aller drei Abfragen und wählen Sie dann die 5 Zeilen mit dem höchsten amount aus :

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

Das Handbuch:

UNION ALL um Duplikate aufzubewahren.

Zum Hinzufügen der Anzahl für jede 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;

Der knifflige Teil hier ist, dass nicht jede event_id wird in allen drei Basisabfragen vorhanden sein. Achten Sie also darauf, dass ein JOIN verliert Zeilen nicht vollständig und Ergänzungen ergeben nicht NULL .

Verwenden Sie UNION ALL , nicht UNION . Sie möchten identische Zeilen nicht entfernen, Sie möchten sie hinzufügen.

x ist ein Tabellenalias und eine Abkürzung für AS x . Es ist erforderlich, dass eine Unterabfrage einen Namen hat. Kann hier jeder andere Name sein.

Die SOL-Funktion FULL OUTER JOIN ist in MySQL nicht implementiert (ich habe das letzte Mal nachgesehen), also müssen Sie sich mit UNION begnügen . FULL OUTER JOIN würde alle drei Basisabfragen verbinden, ohne Zeilen zu verlieren.

Antwort auf Folgefrage

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;

Oder um die Basiszahlen auf verschiedene Weise zu verwenden:

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;