mysql 取出分組后價格最高的數據


如何用mysql 取出分組后價格最高的數據 ? 

看到這個問題,就想到了用 max 函數和 group by 函數,先 group by 然后取得 max, 但是這樣真的可以嗎? 不可以 !

為什么? 因為要了解 :group by 后,select 取出的默認只是每個分組的第一條數據,但是這條數據和選出的 max,很有可能並不是同一條中的。

比如我們表的內容是這樣的:

 

嘗試一(失敗)

執行sql語句 select *  from test_group group by num; 得到的結果:

執行sql語句 select * , max(price) from test_group group by num; 得到的結果:

發現 max price 的價格和當前這條數據的實際價格根本對應不起來。由此可見: 這種寫法其實是錯誤的,取出來的數據沒有任何含義

嘗試二(失敗)

在網上看到這樣一種寫法:既然分組就取第一條數據,那我們先把表排序,再從排序的表中去分組取第一條數據

 select *  from test_group order by price desc;

再從這個表中去分組取得第一條數據:select * from (select *  from test_group order by price desc) as s group by s.num;

經過實際試驗后,發現結果並不對,看一位博主介紹說,mysql 5.7之后對於這個順序好像進行改變了,所以使用這個語句要特別小心mysql版本。

嘗試三(失敗)

另外還有一種寫法是:先取得每個num下最大的price, 再根據得到的price去找對應的數據

select max(price) from test_group group by num;

 select * from test_group where price in (select max(price) from test_group group by num);

看起來可以了,是取出的每組下面最大的數據,但是如果遇到下面這種情況就會有問題啦!

我們加了八八這條數據,屬於 12 組下 價格為130的數據,這樣最終的結果 四四 和 八八都被篩選出來了 !!因為我們篩選出來的max(price) 有130,而八八的價格恰好是130。

 

優化嘗試三(成功)

可以優化下上面這條sql:我們選擇max(price)時還把對應的組也篩選出來,去判斷兩個的num也是相同的,這就需要做一個表的連接

首先得到num及num下的最高價格:select num, max(price) as max_price from test_group group by num;
  

將上面的子表與原表進行連接,條件是num和price都要相同,得到結果如下:
select * from test_group as s1 left join (select num, max(price) as max_price from test_group group by num) as s2 on s1.num=s2.num and s1.price=s2.max_price;

 然后我們篩選出s2.num 不為空的數據即可

select s1.id as id, s1.num as num, s1.price as price, s1.name as name from test_group as s1 left join (select num, max(price) as max_price from test_group group by num) as s2 on s1.num=s2.num and s1.price=s2.max_price where s2.num is not null;

 

 

嘗試四(成功)

我們將表自連接,連接條件是:1的價格<2的價格並且部門相同,這樣的話那些價格最高的不會有數據和它連接,最后篩選2中id is null 的數據就可以了

先將表自連接:select * from test_group s1 left join test_group s2 on s1.price < s2.price and s1.num=s2.num;

 

 

篩選 s2.id is null 的數據:

select s1.id as id, s1.num as num, s1.price as price, s1.name as name from test_group s1 left join test_group s2 on s1.price < s2.price and s1.num=s2.num where s2.id is null;

 

  

這樣得到的結果和上面也一樣

嘗試五(未經過測試)

使用partition by函數來實現,但是這個函數只在mysql 8版本上運行,我的是5.7,太低了,運行不起來,沒有經過驗證。 這個函數也可以用在hive表中

 over(partition by num order by price desc) : 這個語句的意思是先按照 num 進行分組,組內再按照price進行排序

row_number()over(partition by cno order by degree desc) mm: 這個語句的意思是對於上面的結果每組內進行編號,且這列編號列名為 mm

SELECT *
FROM (select sno,cno,degree,
row_number()over(partition by cno order by degree desc) mm
from score)
where mm = 1;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM