Mit über 1800 getaggten Fragen zu greatest-n-per-group
und einigen exzellenten Antworten dachte ich, ich würde eine Lösung für dieses Problem finden - aber ich habe es entweder verpasst Die Lösung oder ich brauche einen neuen Ansatz.JOIN mit `greatest-n-pro-group` und SUM in Unterabfrage
Ich habe eine Tabelle photo_types
, um Stimmen von user
zu speichern, die abstimmen (oben oder unten) auf, was bestimmte photo_type
sie denken, dass ein bestimmtes Foto ist. Fototypen sind 1-10
und jede Stimme wird 1
oder -1
sein.
+----+-----+-----------+------------+------+
| id | user | photo_id | photo_type | vote |
+----+------+----------+------------+------+
| 1 | jane | photo1 | 1 | 1 |
| 2 | jane | photo2 | 2 | 1 |
| 3 | jane | photo3 | 4 | -1 |
| 4 | ben | photo1 | 1 | 1 |
| 5 | ben | photo2 | 3 | -1 |
| 6 | ben | photo2 | 2 | 1 |
| 7 | mary | photo1 | 1 | -1 |
| 8 | mary | photo3 | 10 | 1 |
| 9 | mary | photo2 | 1 | 1 |
| 10 | mary | photo1 | 2 | -1 |
+----+------+----------+------------+------+
Ich muss links auf diese Tabelle zu einem photos
Tisch kommen zurück (das alle anderen Details eines bestimmten Foto hat) - aber sind nur die Besten 2 Arten gewählt für jedes Foto.
Die photos
Tabelle, auf die ich brauche die photo_types
Tabelle sieht LEFT JOIN
wie:
+----+----------+------------+----------------+---------------+------------+
| id | photo_id | photo_name | photographer | location | date |
+----+----------+------------+----------------+---------------+------------+
| 1 | photo1 | the bridge | Bill Murray | Brooklyn, NY | 2012-10-11 |
| 2 | photo2 | the cat | Jacques Chirac | Paris, France | 2013-01-03 |
| 3 | photo3 | a car | the Grinch | London, UK | 2016-09-01 |
+----+----------+------------+----------------+---------------+------------+
ich natürlich bin die beiden Tabellen über photo_id
verbinden.
die oben stimmten Typen für jedes Foto, um erhalte ich eine Unter Abfrage wie folgt versucht:
SELECT photo_id, photo_type, sum(vote) AS votes
FROM photo_types
GROUP BY photo_type, photo_id
HAVING votes>0
ORDER BY votes DESC
welche Gruppen die Summe der Stimmen durch photo_type
sowie photo_id
.
Dies funktioniert gut, aber enthält alle Typen mit sum(vote) > 0
- nicht nur die Top-2-Stimmen.
SQL Fiddle here
Wenn in der Join enthalten sie wie folgt aussieht:
SELECT *
FROM photos
LEFT JOIN
(SELECT photo_id, photo_type, sum(vote) AS votes
FROM photo_types
GROUP BY photo_type, photo_id
HAVING votes>0
ORDER BY votes DESC) AS pt
ON photos.photo_id = pt.photo_id
WHERE photos.date > '2010-01-01';
ich gehofft hatte Bill Karwin's solution zu verwenden, aber ich habe Probleme mit der Tabelle mit sich selbst verbinden, basierend auf den gruppierten Werte (Das ist ein SUM
in meinem Fall). Die Unterabfrage Ich habe versucht, sah aus wie:
SELECT pt1.*, SUM(pt1.vote) AS votes1, SUM(pt2.vote) AS votes2
FROM photo_types AS pt1
LEFT OUTER JOIN photo_types AS pt2
ON pt1.photo_id = pt2.photo_id
AND (votes1 < votes2
OR (votes1 = votes2 AND pt1.id < pt2.id))
WHERE pt2.photo_id IS NULL
... was da nicht funktioniert, es ist ein Versuch, zwei Tabellen auf einem berechneten Wert zu verbinden (im Gegensatz zu Bill-Lösung).
SQL Fiddle here
Frage
Gibt es eine Möglichkeit, die greatest-n-per-group
zu erhalten, wenn die Gruppierung auf einem berechneten Werte wie SUM(xxx)
beruht?
Lösungen, die dies teilweise abdecken, sind here und here, aber keine Aggregate in den gruppierten Werten. Der andere offensichtliche Weg, dies zu tun, besteht darin, einfach die höchsten gewählten Werte jedes Mal neu zu berechnen, wenn eine Stimme platziert wird, und dies direkt in der photos
Tabelle - as discussed here - zu speichern - es sei denn, es ist unmöglich - würde ich lieber innerhalb rechnen die SELECT
aus verschiedenen Gründen.
Wo ist das gewünschte Ergebnis? – Strawberry
@Strawberry wie per http://sqlfiddle.com/#!9/2029d8/7, aber nur die Top-2-Stimmen für jede photo_id enthalten. – goredwards