mysql獲取所有分類的前n條記錄的兩種方法淺析


 

項目中有個需求是獲取出展會分類下的前n條展商。

剛開始的思路是用group by 獲取出展會的分類,后面再根據分類獲取該分類下的n個展商,但也需要第一次獲取出展會的時候也獲取所有的每個展會分類下的n條展商。

 

CSDN上的有一個類似的問題:mysql中有個表:article(字段:id,type,date),type有1-10,10種類型。現在要用SQL找出每種類型中時間最新的前N個數據組成的集合。

 

select a1.* from article a1

inner join

(select a.type,a.date from article a left join article b

on a.type=b.type and a.date<=b.date

group by a.type,a.date

having count(b.date)<=N

)b1

on a1.type=b1.type and a1.date=b1.date

order by a1.type,a1.date desc

用一條SQL語句實現了

 

由於不是很理解這條語句的運行機制,拆分語句去測了一下

 

根據上面這條語句新建了一個test1數據表  有123 3種分類,對應有時間

 

 

 

 

 

表left join 自身獲取數據符合預期

 

Left join  的條件改為 on a.type=b.type and a.date<=b.date,比上一次多了一個條件  a.date<=b.date

 

加入a.date<=b.date之后left join 出來的結果少了一些

 

 

我對left join on 的理解:每一條符合條件的b表記錄都會附加在a表對應記錄后(類似加字段),有多個符合條件的b表記錄對應a表記錄時,這是一對多的關系,a表記錄會復制一個記錄再往后面添加b記錄字段,最后合成一張新的a表。

然后left join 整體流程是 數據庫先取得 a表全部數據,再根據 a.type=b.type and a.date<=b.date取得 b表相關數據
然后拼接組裝出 a.*,b.*的合成數據並返回

 

再對結果集group by a.type,a.date

 

同理把group by  a.type,a.date   改為 group by  b.type,b.date  也可按照這種思路對 btype, bdate 分組

 

后面的having count(b.date)<=N 就好理解了,對分組后的數據過濾,取得符合條件的數據,就是最新的前n條數據。這里的b.date改成a.date結果是一樣的。

 

最后用這種方法實現了效果

select a.* from exhibitor a left join exhibitor b

on a.exhibitionid = b.exhibitionid and a.exhibitorid <= b.exhibitorid

group by  a.exhibitionid ,a.exhibitorid

having count(b.exhibitorid) <=5

 

但是數據量大的時候效果不理想。

 

最后用這種辦法實現取得前n條數據

string sql = @"SELECT * FROM (SELECT *, @num := if(@exhibitionid = exhibitionid, @num := @num + 1, 1) as row_num,@exhibitionid := exhibitionid FROM exhibitor order by exhibitionid) as temp WHERE row_num <=5";

 

展商按展會id排列,把exhibitionid 賦值給@exhibitionid ,@num根據@exhibitionid 是否等於當前exhibitionid,等於num+1,不等於說明遇到了新的分類,num重新等於1,最后得到每個展會下面的展商按照row_num從1開始排列。篩選出row_num <=N,即可選出前n條記錄。

 

附:

1、

mysql 中“:=” 是真正意義上的賦值操作,左邊的變量設置為右邊的值。

"=" 則只在兩種情況下作為賦值用,第一種就是在SET語句里面,SET var = value;

另一種是在UPDATE語句里面的那個SET,如update table_name set  column_name where....。

除了方面這兩種情況外"="則作為比較操作符使用。

 

2、

select * from tablea a inner join tableb b on a.id=b.aid 就相當於 select * from tablea a,tableb b where a.id=b.aid
沒什么區別,寫法不一樣,后者更利於擴展和移植,因為有的數據庫是不支持inner join的

 

3、

查詢hm有重復的記錄

select hm,count(*) from a group by hm having count(*)>1

查詢hm和xm都有重復

select hm,xm count(*) from a group by hm,xm having count(*)>1

 

 

嗯,寫完了,果然寫亂了,算是我的第一篇文章,就當做我的個人筆記吧,還請多多包涵。2016的最后一天,好冷。加油!

 


免責聲明!

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



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