我一直在練習 SQL,遇到了我無法解釋的這種行為。(我也是問這個問題的人:Over() 函式不涵蓋表中的所有行)-> 這是一個不同的問題。
假設我有一張這樣的桌子
電影評分表:
| 電影編號 | 用戶身份 | 評分 | created_at |
|---|---|---|---|
| 1 | 1 | 3 | 2020-01-12 |
| 1 | 2 | 4 | 2020-02-11 |
| 1 | 3 | 2 | 2020-02-12 |
| 1 | 4 | 1 | 2020-01-01 |
| 2 | 1 | 5 | 2020-02-17 |
| 2 | 2 | 2 | 2020-02-01 |
| 2 | 3 | 2 | 2020-03-01 |
| 3 | 1 | 3 | 2020-02-22 |
| 3 | 2 | 4 | 2020-02-25 |
我想做的是按評級對電影進行排名,我有這個 SQL 查詢:
SELECT
movie_id,
rank() over(partition by movie_id order by avg(rating) desc) as rank_rate
FROM
MovieRating
從我之前的問題中,我了解到over()函式將在查詢選擇的視窗中運行,基本上是此查詢回傳的視窗:
SELECT movie_id FROM MovieRating
所以我希望在這里至少看到 3 行,分別對應 id 1、2 和 3。
然而,結果只有一行:
{"headers": ["movie_id", "rank_rate"], "values": [[1, 1]]}
這是為什么 ?我對功能如何作業的理解有問題over()嗎?
uj5u.com熱心網友回復:
您需要一個聚合查詢并RANK()對其結果使用視窗函式:
SELECT movie_id,
AVG(rating) AS average_rating, -- you may remove this line if you don't actually need the average rating
RANK() OVER (ORDER BY AVG(rating) DESC) AS rank_rate
FROM MovieRating
GROUP BY movie_id
ORDER BY rank_rate;
請參閱演示。
您的查詢是沒有group by子句的聚合查詢,這意味著它對整個表而不是每個表進行操作movie_id。此類查詢僅回傳 1 行的聚合結果。
當您應用RANK()視窗功能時,它將對該單行而不是表格進行操作。
uj5u.com熱心網友回復:
我認為您的意思是為每部電影獲得一排平均評分。
您應該使用GROUP BY,而不是視窗函式:
SELECT movie_id, AVG(rating) AS avg_rating
FROM MovieRating
GROUP BY movie_id
ORDER BY avg_rating DESC;
https://www.db-fiddle.com/f/o9qLFbJEwhaHDWoTS9Qfwp/1
你只得到一行的原因是,當你使用一個聚合函式時AVG(),它會隱式地將查詢變成一個聚合查詢。查詢的結果是每組一行。
https://dev.mysql.com/doc/refman/8.0/en/aggregate-functions.html說:
如果在不包含 GROUP BY 子句的陳述句中使用聚合函式,則相當于對所有行進行分組。
換句話說,如果您使用AVG()但未指定GROUP BY運算式,則將整個表視為一個“組”。因為整個表是一個組,所以結果是一行。
視窗函式定義的視窗與聚合函式定義的組不同。在通過聚合減少行之后應用視窗函式。由于只有一組,因此您的結果中只有一行,因此排名為 1。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/464326.html
