[Linq / Lambda / Entity Framework / VB.NET] Left Join兩資料表,透過Lambda實現SQL的Row_Number, Partition By

使用Linq Left join 兩個關聯資料表後,再使用Lambda實現Row_Number,Partition by
進而實現在EntityFrameWork下做出重複資料中各群組的特定一筆資料

最近開始玩EntityFrameWork,把一些SQL Command改掉感覺真舒服
但是碰到了一個難題 只好各個擊破

要實現三件事情

1.Left Join

2.Partition by

3.Row_Number()

總之圖表長這樣,Contra_Renew紀錄每個合約資料(中文Table見怪不怪 ...)的續約紀錄
 

PrimaryKey= 合約資料.No
ForeignKey=CONTRA_RENEW.ContraCorreCode

1.Left Join

Public Function LeftJoinList(QueryValue As String)
    Using Context As New MerchantDB
        Dim getContra = (From data In Context.合約資料
                         From renewData In Context.CONTRA_RENEW.Where(Function(r) r.ContraCorreCode = data.No).DefaultIfEmpty
                         Where data.CustName = QueryValue
                         Select New With {
                                .col1 = data.col1,
                                .col2 = data.col2,
                                .col3 = data.col3,
                                .col4 = data.col4}).ToList
         Return getContra 
    End Using
End Function

Linq的Join比較繁複一點 思考邏輯比較不同,前輩保哥在幾年有寫過相關文章

 


 

2.Row_Number / Partition by 

Public Function LeftJoinList(QueryValue As String)
    Using Context As New MerchantDB
        Dim getContra = (From data In Context.合約資料
                         From renewData In Context.CONTRA_RENEW.Where(Function(r) r.ContraCorreCode = data.No).DefaultIfEmpty
                         Where data.CustName = QueryValue
                         Select New With {
                                .col1 = data.col1,
                                .col2 = data.col2,
                                .col3 = data.col3,
                                .col4 = data.col4}).ToList

        Dim PartitionByContra = (getContra.GroupBy(Function(gb) gb.ContraNo).Select(Function(G) New With{Key .group = G,Key .Count = G.count()}).
                                SelectMany(Function(sm) sm.group.OrderByDecending(Function(obd) obd.ContraIniDate).
                                Zip(Enumerable.Range(1,sm.Count),Function(J,I) New With {Key .OrderNo = I,J.col1,J.col2,J.col3,J.col4,J.col5})).
                                Where(Function(Final) Final.OrderNo = 1)).ToList


         Return PartitionByContra 
    End Using
End Function

我們直接從LeftJoinList加入另一個Lambda,從Lambda裡可以看到我做了幾件事情
 

1.先透過ContraNo這欄位,使用GroupBy來分類

2.在SelectMany中,我先將第一個GroupBy後的群組進行排序(因為我要的是最新的合約續約起始/到期日,可以看到我是對ContraIniDate的排序是Decending),再對sm的Count進行查詢

3.使用Zip將Sm.Count逐筆放到新的序列中,最後使用Where設定條件,此時資料已經明確分為各群組,且各群組內的元素皆有排序編號,要找最新的續約日期就很簡單了

ZIP資料解說這邊看
C#版本這裡看(StockOverFlow)

單純筆記,皆為非正規作法,旁門左道,胡搞瞎搞。