2016-11-24 76 views
2

我想知道是否有可能到另一列添加到包含像最小值,最大值聚合函數select語句...SQL MIN函數和其他列

例如:

SELECT user_id, MAX(salary) FROM users; 

這個語句是否正確在sql標準中(在mysql的工作中); 它在mysql中的工作,但我想我讀的地方,如果我把一個聚合函數在select子句中,我不能放任何東西,但聚合函數或如果有一個組,通過分組列可以在選擇條款(在MySQL)


EDIT

User(user_id, name, last_name, salary) 

我想選擇從Useruser_id, name, (maximum salary column);有沒有可能做到沒有子查詢?

用戶表

User_id, Name, Salary 

| 1 | user1 | last1 | 500 | | 
|---|-------|-------|------|---| 
| 2 | user2 | last2 | 1000 | | 
| 3 | user3 | last3 | 750 | | 
| |  |  |  | | 

輸出必須user_id, username, lastname, and salary of the user who have the max salary,所以這裏的輸出中必須做到:

2 user2 last2 1000 

+0

取決於你想要做什麼,MySQL does not folllow ansi標準關於聚合函數和組,所以你可以做一些不允許在其他數據庫中的快捷方式。 –

+0

@scaisEdge它使用group by,它會返回每個元組user_id的最大值(工資),這與使用'SELECT user_id,name,salary'相同。 – karim

+1

btw您應該向我們展示示例數據和預期輸出。這個問題可以根據你的需要改變。 –

回答

1

告訴你有這取決於你想要什麼不同的解決方案....

沒有GROUP BY,無子查詢,輕鬆蛋糕

select * 
from users 
ORDER BY salary DESC 
LIMIT 1 
1

讓我們來看一個例子:

mysql> select * from users; 
+---------+----------+ 
| user_id | salary | 
+---------+----------+ 
|  1 | 42000.00 | 
|  2 | 39000.00 | 
|  3 | 50000.00 | 
+---------+----------+ 

mysql> SELECT user_id, MAX(salary) FROM users; 
+---------+-------------+ 
| user_id | MAX(salary) | 
+---------+-------------+ 
|  1 | 50000.00 | 
+---------+-------------+ 

那是怎麼回事?用戶1不是薪水爲50000.00的用戶。

mysql> SELECT user_id, MAX(salary), MIN(SALARY) FROM users; 
+---------+-------------+-------------+ 
| user_id | MAX(salary) | MIN(SALARY) | 
+---------+-------------+-------------+ 
|  1 | 50000.00 | 39000.00 | 
+---------+-------------+-------------+ 

用戶1也不是39000.00的用戶。這是越來越腥,對嗎?

當您使用聚合函數時,它們只適用於您使用該函數的列。user_id列不會奇蹟般地知道哪個最大值來自哪行,並顯示相應的user_id。

在那個例子中,我查詢MAX和MIN工資。但是這些屬於不同的用戶!哪個user_id應該顯示,即使user_id可以自動從聚合值來自的行中?

如果兩個用戶有相同的薪水,這與最高薪水並列,會出現什麼情況?應顯示哪個user_id?

如果您使用不返回任何單行上存在的值的聚合函數,該怎麼辦?

mysql> SELECT user_id, AVG(salary) FROM users; 
+---------+--------------+ 
| user_id | AVG(salary) | 
+---------+--------------+ 
|  1 | 43666.666667 | 
+---------+--------------+ 

下面是解釋:聚合函數導致結果減少到一行後,讀取整個行組。不在聚合函數內的列(如user_id)從行組中的某個任意行獲取其值。任意並不意味着隨機在實踐中,它往往是該組中第一個MySQL行讀取。但不能保證永遠是這樣。

這個有用嗎?不是特別的。在其他數據庫中,這不是一個有效的查詢,它會從字面上產生一個錯誤。

事實上,MySQL 5.7改變了行爲,通過強制執行不允許模棱兩可的查詢的規則。如果試圖在MySQL 5.7運行上面的查詢,它會產生一個錯誤:

ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'test.users.user_id'; this is incompatible with sql_mode=only_full_group_by

有使它像早期版本的MySQL的一個選項。有關這方面的更多信息,請參閱:https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html

作爲一個小問題,SQLite是允許這種任意結果的另一個數據庫。只有在SQLite中,user_id的值將來自組中讀取的最後一個行。去搞清楚。

+1

感謝您提供這個有價值的答案,但您能否爲我解決這個問題? – karim

+1

我非常喜歡這個解釋。查詢中非聚合user_id的誤解不可能變得更加明顯。 –

+0

@卡里姆,胡安卡洛斯給出了最簡單的解決方案。 –

2

首先:沒有,

SELECT user_id, MAX(salary) FROM users; 

不符合標準。您正在使用不具有GROUP BY子句的聚合函數(MAX)。通過這樣做,您可以告訴DBMS將所有記錄聚合到一個結果行。現在你告訴DBMS在這個結果行中顯示什麼?表中找到的最高工資(MAX(salary))和user_id。但是,沒有user_id;表中可能有許多不同的user_id。這違反了SQL標準。 MySQL可以自由地將非聚合的user_id解釋爲任意user_id(任意挑選)。

所以即使查詢運行,它的結果通常不是所需的結果。

這個查詢:

SELECT user_id, name, MAX(salary) FROM users GROUP BY user_id; 

,另一方面是符合標準的。讓我們再看看這個查詢的作用:這一次有GROUP BY子句告訴DBMS你想要一個結果行,每user_id。對於您要顯示的每個user_iduser_id,name和最大值salary。所有這些都是有效的表達; user_iduser_id本身名稱是與user_id關聯的一個用戶名,而最大值salary是用戶的最高工資。允許使用未分類的列name,因爲它在功能上依賴於分組user_id。但是,許多DBMS不支持這一點,因爲確定一個表達式在功能上是否依賴於該組可能會變得非常複雜。

至於如何以最高工資顯示用戶記錄,您需要一個限制條款。 MySQL爲此提供了LIMIT,它可以爲您提供前n行。但它並不處理關係。

SELECT * FROM users ORDER BY salary DESC LIMIT 1; 

SELECT * FROM users ORDER BY salary FETCH FIRST ROW ONLY; 
標準SQL

不過,爲了應對關係,在

SELECT * FROM users ORDER BY salary FETCH FIRST ROW WITH TIES; 

你需要在MySQL子查詢,因爲LIMIT不支持這一點:

SELECT * FROM users WHERE salary = (SELECT MAX(salary) FROM users);