項目中有個需求是獲取出展會分類下的前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的最后一天,好冷。加油!
