测一测自己的Sql能力之MYSQL的GROUPBY你弄懂了吗?
場景描述如下:
訂單表
(包含字段有:訂單ID[自增]、客戶ID、下單時間、訂單金額、商品名稱),
采用一個SQL語句,查詢出:
每一位客戶最后一次的下單時間、訂單金額、商品名稱;以及每一位客戶的累計訂單總筆數、最大訂單金額
看起來很簡單哈,有的同學就會這樣去寫了,如下:
SELECTMAX( good_price ) AS max_good_price,COUNT( DISTINCT order_id, order_id ) AS sum_order_num,order_person_id,MAX( create_time ) AS create_time,good_price,order_name AS good_name FROM`t_order_info` GROUP BYorder_person_id在數據很少的時候,通過這種就很容易實現了,并且每一個用戶當時只有一條對應的信息,也就是order_person_id所對應的商品信息只有互不相同的一條信息。
很顯然這樣是不合理的,當出現多條數據的時候就會產生對應的一個錯誤,那就是會取到其他的數據,顯示的order_person_id為3,但卻不是3的其他數據字段。所以當我們去查詢的時候 發現數值不對。
然后繼續查看是那種原因呢?
首先我們一定要明白,GROUPBY是每次只取表格的第一條數據,比如按照order_person_id進行分類,這樣就會每次遇到相同的order_person_id時候,就會取第一個職,這樣就出現了上面所展示的結果。
所以首先我們可以先查出來每個下單人所對應的最新下單時間以及下單人order_person_id編號,這樣我們在拿著這組編號再去聯查原始表INNER JOIN,將我們的時間最大值和其他相關字段查出來,同時要按照下單人ID進行分組,這樣查出來的數據存在重復的訂單數據,所以我們再嵌套一層GROUPBY order_person_id,這樣就會按照含有重復數據集合中的默認id順序進行分組并從該順序中逐一取order_person_id的第一個值,然后生成新得集合。
對比兩次GROUPBY查詢:
SELECTtoi.* FROM( SELECT order_person_id, max( create_time ) time FROM t_order_info GROUP BY order_person_id ) tmpINNER JOIN t_order_info toi ON tmp.order_person_id = toi.order_person_id AND tmp.time = toi.create_time ORDER BY order_person_id DESC根據order_person_id進行排序查詢,結果如下: 1723 小卡車 3 3 1724 小卡車 4 4 1572 小卡車-AB 5 5 1708 小卡車 6 6 1717 小卡車 6 6 1709 小卡車 7 7 1718 小卡車 7 7 1710 小卡車 8 8 1719 小卡車 8 8 1702 小卡車 9 9 1711 小卡車 9 9 1720 小卡車 9 9 1703 小卡車 10 10 1712 小卡車 10 10 1721 小卡車 10 10 1722 小卡車 11 11SELECTtoi.* FROM( SELECT order_person_id, max( create_time ) time FROM t_order_info GROUP BY order_person_id ) tmpINNER JOIN t_order_info toi ON tmp.order_person_id = toi.order_person_id AND tmp.time = toi.create_time 默認GROUPBY 分組ID排序 1572 小卡車-AB 5 5 7 1702 小卡車 9 9 7 1703 小卡車 10 10 7 1708 小卡車 6 6 7 1709 小卡車 7 7 7 1710 小卡車 8 8 7 1711 小卡車 9 9 7 1712 小卡車 10 10 7 1717 小卡車 6 6 7 1718 小卡車 7 7 7 1719 小卡車 8 8 7 1720 小卡車 9 9 7 1721 小卡車 10 10 7 1722 小卡車 11 11 7 1723 小卡車 3 3 7 1724 小卡車 4 4 7正式的SQL例子,采用INNERJOIN:
SELECT * FROM (SELECT toi.*FROM (SELECT order_person_id,max(create_time) TIMEFROM t_order_infoGROUP BY order_person_id) tmpINNER JOIN t_order_info toi ON tmp.order_person_id = toi.order_person_idAND tmp.TIME = toi.create_time) AS a GROUP BY order_person_id; -- GROUP BY 默認取第一個第二步進行聚合函數的操作:
SELECTMAX( good_price ) AS max_good_price,COUNT( order_id ) AS sum_order_num,MAX( create_time ) AS max_create_time,order_person_id FROM`t_order_info` GROUP BYorder_person_id;最終版本:
最終版: SELECTMAX( toi1.good_price ) AS max_good_price,COUNT( toi1.order_id ) AS sum_order_num,toi1.order_person_id,max_create_time, b.good_price,b.order_name,b.order_person_id FROM`t_order_info`AS toi1 INNER JOIN (SELECT max(create_time) AS max_create_time, good_price,order_name,order_person_id FROM(SELECTtoi.* FROM( SELECT order_person_id, max( create_time ) time FROM t_order_info GROUP BY order_person_id ) tmpINNER JOIN t_order_info toi ON tmp.order_person_id = toi.order_person_id AND tmp.time = toi.create_time ) AS a GROUP BY order_person_id) AS b ON toi1.order_person_id = b.order_person_idGROUP BYb.order_person_id還可以根據最新的時間進行分組,不采用INNERJOIN的形式。
SELECT * FROM ( SELECTorder_id,order_person_id,good_price,order_name AS good_name,create_time FROM`t_order_info` WHERE create_time = (SELECTMAX( create_time )) GROUP BYorder_person_id,(SELECT MAX( create_time )) ORDER BYcreate_time DESC ) AS a GROUP BYorder_person_id最終版本:
最終版: SELECTMAX( toi.good_price ) AS max_good_price,COUNT( toi.order_id ) AS sum_order_num,MAX( toi.create_time ) AS max_create_time,toii.good_price,toii.good_name,toii.order_person_id FROM`t_order_info` AS toiINNER JOIN (SELECT* FROM( SELECT order_person_id, good_price, order_name AS good_name, create_time FROM `t_order_info` GROUP BY order_person_id, ( SELECT MAX( create_time )) ORDER BY create_time DESC ) AS a GROUP BYorder_person_id ) AS toii ON toi.order_person_id = toii.order_person_id GROUP BYtoii.order_person_id以下是其他排查語句,也先列在這里。
SELECT max(create_time), order_person_id FROM t_order_info GROUP BY order_person_id;SELECT max(create_time), good_price,order_name,order_person_id FROM t_order_info GROUP BY order_person_id;同時這里面里一個終極版本的寫法:
select temp.order_person_id 客戶ID,max(temp.create_time) 最后一次的下單時間,temp.good_price 最后一次的下單金額,temp.order_name 最后一次的下單商品,count(*) 客戶的累計訂單總筆數,max(good_price) 最大訂單金額 from (select * from t_order_info order by create_time desc, order_id desc limit 9999999999) as temp group by temp.order_person_id;這是我的直屬領導給我寫的語句,多么的簡短,美麗大方,留做紀念。
歡迎感興趣的小伙伴一起探討學習知識,以上是個人的一些總結分享,如有錯誤的地方望各位留言指出,十分感謝。
覺得有用的話別忘點贊、收藏、關注,手留余香! 😗 😗 😗
總結
以上是生活随笔為你收集整理的测一测自己的Sql能力之MYSQL的GROUPBY你弄懂了吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 与,或,非,异或,左移,右移,位运算符号
- 下一篇: SQL语句之操作表记录(CRUD)