本來開發時有一個分組聚合的腳本,比較複雜,爲了筆記效果,所以將腳本做一個簡化。
本來庫裏有兩個表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()查詢就完成了。
如果對你有幫助,點贊支持一下,謝謝!