亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

SQL如何實現組內排序取最大值

發布時間:2021-11-01 10:54:39 來源:億速云 閱讀:652 作者:小新 欄目:MySQL數據庫

這篇文章主要介紹了SQL如何實現組內排序取最大值,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

測試用例

--建表
create table testorder
(id int not null,
no int not null,
name char(10) not null,
primary key(id)
)engine=innodb;
--寫入數據
insert into testorder values (1,1,'Mike'),(2,2,'John'),(3,3,'wyett'),(4,4,'Herry'),(5,5,'Mike'),(6,1,'John'),(7,2,'John'),(8,1,'Mike'),(9,1,'Mike');
--查詢1
select * from testorder;
+----+----+-------+
| id | no | name  |
+----+----+-------+
|  1 |  1 | Mike  |
|  2 |  2 | John  |
|  3 |  3 | wyett |
|  4 |  4 | Herry |
|  5 |  5 | Mike  |
|  6 |  1 | John  |
|  7 |  2 | John  |
|  8 |  1 | Mike  |
|  9 |  1 | Mike  |
+----+----+-------+
--查詢2
select * from testorder order by no desc;
+----+----+-------+
| id | no | name  |
+----+----+-------+
|  5 |  5 | Mike  |
|  4 |  4 | Herry |
|  3 |  3 | wyett |
|  2 |  2 | John  |
|  7 |  2 | John  |
|  1 |  1 | Mike  |
|  6 |  1 | John  |
|  8 |  1 | Mike  |
|  9 |  1 | Mike  |
+----+----+-------+
--查詢3 select * from (select id,no,name from testorder order by no desc)a group by a.name;

查詢3這條SQL是我們需要討論的內容,也是業務線為實現組內排序取最大值所采用的SQL。標準的程序員反饋問題方式:XXX時間點之前查詢時正常的,這之后突然就不正常了,你們DBA是不是做什么改動了?我把數據恢復到自己的測試機,返回值也是正常的。暫且不去管姿勢是否正確,對這條SQL的分析,我們其實可以看出:(1)程序員期待group by執行結果是按照臨時表a的數據順序來取值;(2)程序員未考慮版本因素,數據量變化的因素;為此,我構建了上面的測試用例。

測試

在不同版本的MySQL來進行測試:發現在Percona 5.5,Percona 5.1,MySQL 5.6關閉sql_mode= ONLY_FULL_GROUP_BY,MySQL5.1等版本下,返回值確如程序員期待的順序,按照order by no desc的順序,相同name返回no值最大的數據;

+----+----+-------+
| id | no | name  |
+----+----+-------+
|  4 |  4 | Herry |
|  2 |  2 | John  |
|  5 |  5 | Mike  |
|  3 |  3 | wyett |
+----+----+-------+

在mysql5.7,關閉sql_mode= ONLY_FULL_GROUP_BY和mariadb 10.*版本中,相同的name值,返回則是取了最早寫入的數據行,忽略了order by no desc,按照數據的邏輯存儲順序來返回;

+----+----+-------+
| id | no | name  |
+----+----+-------+
|  4 |  4 | Herry |
|  2 |  2 | John  |
|  1 |  1 | Mike  |
|  3 |  3 | wyett |
+----+----+-------+

其實在這里,SQL等價于select id,no,name from testorder group by name。
這里我們看出不同版本的返回值是不同的,先擱置數據量的變化引起執行結果不同的討論,因為數據量大小很難測試。

官方文檔

對上面的測試結果,在官方文檔上,有如下的參考

If ONLY_FULL_GROUP_BY is disabled...In this case, the server is free to choose any value from each group, 
so unless they are the same, the values chosen are indeterminate, which is probably not what you want. 
Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. 
Result set sorting occurs after values have been chosen, and ORDER BY does not affect which value within 
each group the server chooses.

ONLY_FULL_GROUP_BY這個SQL_MODE出在mysql5.6(mariadb 10.0)時被引入,但本文討論的內容和它無關,具體可以自己查看文檔,這里不做討論。在5.6,5.5的官方文檔有相同的內容,Mariadb也有類似的解釋

 If you select a non-grouped column or a value computed from a non-grouped column, it is undefined 
which row the returned value is taken from. This is not permitted if the ONLY_FULL_GROUP_BY SQL_MODE is used.

并且,對from后的subquery子表中的order by也給出了解釋

 A query such as

SELECT field1, field2 FROM ( SELECT field1, field2 FROM table1 ORDER BY field2 ) alias
returns a result set that is not necessarily ordered by field2. This is not a bug.

A "table" (and subquery in the FROM clause too) is - according to the SQL standard - an unordered set of rows. 
Rows in a table (or in a subquery in the FROM clause) do not come in any specific order.

好了,有了這些解釋,問題很明朗:

  • 在from 后的subquery中的order by會被忽略

  • group by cloumn返回的行是無序的

因此,業務獲得的正確的返回值也是誤打誤撞。

解決辦法

那么這個問題該怎么解決?

在網上有一些SQL,很明顯不滿足需求,在這里做一下展示,希望同學們避免被誤導:

錯誤SQL集合

select id,sbustring(GROUP_CONCAT(distinct no order by no desc separator ''),'',1),name from testorder group by name;
--通過添加索引來影響返回的結果集順序
alter table testorder add index idx_no_name(no desc, name);
--結果證明即使如此,desc也不會被正確執行;
--我司程序員的寫法
select * from (select id,no,name from testorder order by no desc)a group by a.name
select id,max(no),name from testorder group by name

我們可以這樣寫,雖然效率不高

select a.id,a.no,a.name 
from testorder a 
inner join (select max(no) no,name 
            from testorder 
	    group by name) b on a.no=b.no and a.name=b.name 
group by name,no

或者這樣

select a.id,a.no,a.name 
from testorder a 
group by a.name,a.no 
having a.no=(select max(no) from testorder where name=a.name)

感謝你能夠認真閱讀完這篇文章,希望小編分享的“SQL如何實現組內排序取最大值”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

sql
AI

铁力市| 上饶县| 同心县| 彭州市| 礼泉县| 个旧市| 五大连池市| 天长市| 裕民县| 泗水县| 兴海县| 左权县| 普宁市| 天水市| 竹山县| 保山市| 藁城市| 梅河口市| 宁远县| 攀枝花市| 屏东县| 岚皋县| 维西| 宜川县| 宜宾县| 内江市| 拉萨市| 汶川县| 宜春市| 河津市| 宾川县| 池州市| 托克逊县| 瓮安县| 双辽市| 台南县| 安远县| 彭水| 新郑市| 个旧市| 阜城县|