【发布时间】:2017-01-05 00:26:33
【问题描述】:
greatest-n-per-group 有超过 1800 个标记问题和一些出色的答案,我想我会找到解决这个问题的方法 - 但我要么错过了解决方案,要么需要一种新方法。
我有一个表 photo_types 来存储 user 的投票,他们正在投票(向上或向下)他们认为给定照片是什么特定的 photo_type。照片类型为1-10,每张投票为1或-1。
+----+-----+-----------+------------+------+
| 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 |
+----+------+----------+------------+------+
我需要将此表左连接回 photos 表(包含给定照片的所有其他详细信息) - 但仅包括前 2 个投票类型 每张照片。
我需要LEFT JOIN photo_types 表的photos 表如下所示:
+----+----------+------------+----------------+---------------+------------+
| 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 |
+----+----------+------------+----------------+---------------+------------+
我显然是通过photo_id 加入这两个表的。
为了获得每张照片的票数最高的类型,我尝试了如下子查询:
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
将投票总和按photo_type 和photo_id 分组。
这可以正常工作,但包括 sum(vote) > 0 的所有类型 - 不仅仅是前 2 个投票类型。
SQL Fiddle here
当包含在连接中时,它看起来像:
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';
我曾希望使用Bill Karwin's solution,但我无法根据分组值(在我的情况下为SUM)将表连接到自身。我尝试的子查询看起来像:
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
...这不起作用,因为它试图在计算值上连接两个表(与 Bill 的解决方案不同)。
SQL Fiddle here
问题
当分组基于SUM(xxx) 等计算值时,有没有办法获取greatest-n-per-group?
部分解决此问题的解决方案是 here 和 here,但不包括分组值中的聚合。
另一种明显的方法是在每次投票时简单地重新计算最高投票值并将其直接存储在photos 表中 - as discussed here - 但除非不可能 - 我更喜欢由于各种原因,在SELECT 内进行计算。
【问题讨论】:
-
想要的结果在哪里?
-
@Strawberry 与 sqlfiddle.com/#!9/2029d8/7 相同,但仅包括每个 photo_id 的前 2 个投票类型。
标签: mysql sql join greatest-n-per-group