SQL中join group by having max() 時轉Linq

 

本來開發時有一個分組聚合的腳本,比較複雜,爲了筆記效果,所以將腳本做一個簡化。

本來庫裏有兩個表TableA和TableB,兩個表的主鍵做如下關聯:

--TableA的主鍵ID爲TableB的外鍵Aid
SELECT a.Id, a.Name, b.Id, b.Name, b.Aid, b.CreateTime
FROM TableA a
JOIN TableB b ON a.Id=b.Aid

現在需要根據TableA的Aid分組,取出每個Aid對應TableB的最新CreateTime的一個的Name數據,腳本如下:

SQL寫法一:

SELECT 
a.Id, 
b.Name
FROM TableA a
JOIN TableB b ON b.AId=a.Id AND EXISTS (SELECT 1 FROM TableB d WHERE d.AId=b.AId GROUP BY d.AId HAVING b.CreateTime=MAX(d.CreateTime))

根據上面的SQL可見,在join的條件中,我使用了Having作爲聚合後的判斷條件,這個腳本也可以變換爲下面的寫法:

SQL寫法二:

SELECT 
a.Id, 
b.Name
FROM TableA a
JOIN TableB b ON b.AId=a.Id AND EXISTS (SELECT 1 FROM (SELECT d.AId, MAX(d.CreateTime) AS MaxCreateTime FROM TableB d WHERE d.AId=b.AId GROUP BY d.AId) AS d1 WHERE b.CreateTime=d1.MaxCreateTime)

上面的變換寫法,可不是爲了花哨展示,而是因爲Linq本身不能直接轉換SQL寫法一,而可以轉換爲SQL寫法二。


那麼SQL寫法二也爲SQL轉爲Linq提供了一個思路,就是先將最大的CreateTime取出來,然後再作爲條件進行查詢,那麼最終的Linq寫法就出來了:

// 先將CreateTime的Max作爲條件寫好
var wherequery = from a in TableB
                 where (from b in TableB where b.AId == a.AId group b by b.AId into b1 select b1.Max(c => c.CreateTime)).Contains(a.CreateTime)
                 select a;

// 將上面的linq再加入下面的linq中作爲條件:
var aa = from a in TableA
         join b in wherequery on a.Id equals b.AId
         select new
         {
             AId = a.Id,
             b.Name
         };

至此,一個複雜的group by having max()查詢就完成了。

如果對你有幫助,點贊支持一下,謝謝!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章