我将此查询作为练习包含在斯坦福数据库MOOC中遇到了问题:
对于同一评论者对同一部电影进行两次评分并第二次给予更高评价的所有情况,请返回评论者的姓名和电影名称。
有三个表用作练习的一部分:movie, rating and reviewer
。正在使用的系统是SQLite
。
movie;
+----------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+-------+
| mID | int(11) | YES | | NULL | |
| title | text | YES | | NULL | |
| year | int(11) | YES | | NULL | |
| director | text | YES | | NULL | |
+----------+---------+------+-----+---------+-------+
rating;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| rID | int(11) | YES | | NULL | |
| mID | int(11) | YES | | NULL | |
| stars | int(11) | YES | | NULL | |
| ratingDate | date | YES | | NULL | |
+------------+---------+------+-----+---------+-------+
reviewer;
+-------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+---------+------+-----+---------+-------+
| rID | int(11) | YES | | NULL | |
| name | text | YES | | NULL | |
+-------+---------+------+-----+---------+-------+
Expected Query Result:
name title
Sarah Martinez Gone with the Wind
如果有人也想要这些数据,here it is。
答案 0 :(得分:2)
SELECT
W.name,
M.title
FROM
reviewer AS R
INNER JOIN movie AS M
ON EXISTS ( -- there is at least one rating
SELECT *
FROM rating AS G
WHERE
-- by the reviewer and movie in question
R.rID = G.rID
AND M.mID = G.mID
AND EXISTS ( -- for which another rating exists
SELECT *
FROM rating AS G2
WHERE
-- for the same reviewer and movie
R.rID = G2.rID
AND M.mID = G2.mID
AND G.stars < G2.stars -- but rated higher
AND G.ratingDate < G2.ratingDate -- and later
)
)
;
我不能100%确定SQLite是否允许ON
子句有EXISTS
个表达式。如果没有,您只需将EXISTS
表达式移至WHERE
子句,然后在reviewer
和movie
之间执行交叉联接。
如果SQLite不支持EXISTS
,请将EXISTS
个查询作为派生表放在FROM
子句中,并将两个表INNER JOIN
编辑为彼此,然后GROUP BY
mId
和rID
,然后INNER JOIN
到主表。这可能是这样的:
SELECT
R.name,
M.title
FROM
(
SELECT
G.rID,
G.mID
FROM
rating AS G
INNER JOIN rating AS G2
ON G.rID = G2.rID
AND G.mID = G2.mID
AND G.stars < G2.stars
AND G.ratingDate < G2.ratingDate
GROUP BY
G.rID,
G.mID
) C
INNER JOIN reviewer AS R
ON C.rID = R.rID
INNER JOIN movie AS M
ON C.mID = R.mID
;
我希望你能看到这两个查询如何表达相同的语义。在一个非常大的数据库中,人们多次评价相同的电影,可能会有性能差异(我首先显示的EXISTS
版本可以表现得更好,因为它可以在找到一个结果时立即停止。)
注意:您可以将整个混乱加入到单个查询中GROUP BY
name
,title
,rID
,mID
,但同时& #34;更简单&#34;,这将更加错误,因为不需要复制许多行的名称和标题,只是通过分组丢弃该信息。分组应该尽早发生。