LINQ, Join, GroupBy and Count - vb.net

I have this vb.net LINQ query. Without the join the count and SUM worked perfectly on each. But with the join the count and SUM arent working properly due to the multiple CAMPAIGNID values. I suspect I need another group by statement in there but I am not entirely sure how to do that. IF you could help that would be great.
Dim query =
From t1 In tbl1
Join t2 In tbl2 On t1.CAMPAIGNID Equals t2.CAMPAIGNID
Group By t1.CAMPAIGNID Into Group
Select New With {
.id = CAMPAIGNID,
.CALLS = Group.Sum(Function(a) a.t2.CALLS),
.count = Group.Count(Function(a) a.t1.TERMCD = "Refused")
}

I have made an example which seems to be working properly.
Public Class T1
Public Property CAMPAIGNID As Integer
Public Property TERMCD As String
End Class
Public Class T2
Public Property CAMPAIGNID As Integer
Public Property CALLS As Integer
End Class
Dim tbl1 As New List(Of T1) From {
New T1 With {.CAMPAIGNID = 1, .TERMCD = "Refused"},
New T1 With {.CAMPAIGNID = 1, .TERMCD = "Accepted"},
New T1 With {.CAMPAIGNID = 2, .TERMCD = "Refused"},
New T1 With {.CAMPAIGNID = 2, .TERMCD = "Accepted"},
New T1 With {.CAMPAIGNID = 3, .TERMCD = "Refused"},
New T1 With {.CAMPAIGNID = 3, .TERMCD = "Accepted"}
}
Dim tbl2 As New List(Of T2) From {
New T2 With {.CAMPAIGNID = 1, .CALLS = 2},
New T2 With {.CAMPAIGNID = 1, .CALLS = 4},
New T2 With {.CAMPAIGNID = 2, .CALLS = 8},
New T2 With {.CAMPAIGNID = 2, .CALLS = 16},
New T2 With {.CAMPAIGNID = 3, .CALLS = 32},
New T2 With {.CAMPAIGNID = 3, .CALLS = 64}
}
Dim query =
From t1 In tbl1
Join t2 In tbl2 On t1.CAMPAIGNID Equals t2.CAMPAIGNID
Group By t1.CAMPAIGNID Into Group
Select New With {
.id = CAMPAIGNID,
.CALLS = Group.Sum(Function(a) a.t2.CALLS),
.count = Group.Count(Function(a) a.t1.TERMCD = "Refused")
}
For Each q In query
Console.WriteLine($"ID:{q.id}, CALLS:{q.CALLS}, COUNT:{q.count}")
Next
ID:1, CALLS:12, COUNT:2
ID:2, CALLS:48, COUNT:2
ID:3, CALLS:192, COUNT:2
In the case of ID 3, the CALLS sum of 192 is correct because the sum has no constraint of TERMCD = "Refused", so it counts all. And the count of 2 is accurate because has a constraint where TERMCD = "Refused".
Just looking at the group, without aggregation, let's see what is returned
Dim query =
From t1 In tbl1
Join t2 In tbl2 On t1.CAMPAIGNID Equals t2.CAMPAIGNID
Group By t1.CAMPAIGNID Into Group
For Each q In query
Console.WriteLine($"ID:{q.CAMPAIGNID}")
For Each g In q.Group
Console.WriteLine($"t1.CAMPAIGNID:{g.t1.CAMPAIGNID}, t1.TERMCD:{g.t1.TERMCD}, t2.CAMPAIGNID:{g.t2.CAMPAIGNID}, t2.CALLS:{g.t2.CALLS}")
Next
Next
ID:1
t1.CAMPAIGNID:1, t1.TERMCD:Refused, t2.CAMPAIGNID:1, t2.CALLS:2
t1.CAMPAIGNID:1, t1.TERMCD:Refused, t2.CAMPAIGNID:1, t2.CALLS:4
t1.CAMPAIGNID:1, t1.TERMCD:Accepted, t2.CAMPAIGNID:1, t2.CALLS:2
t1.CAMPAIGNID:1, t1.TERMCD:Accepted, t2.CAMPAIGNID:1, t2.CALLS:4
ID:2
t1.CAMPAIGNID:2, t1.TERMCD:Refused, t2.CAMPAIGNID:2, t2.CALLS:8
t1.CAMPAIGNID:2, t1.TERMCD:Refused, t2.CAMPAIGNID:2, t2.CALLS:16
t1.CAMPAIGNID:2, t1.TERMCD:Accepted, t2.CAMPAIGNID:2, t2.CALLS:8
t1.CAMPAIGNID:2, t1.TERMCD:Accepted, t2.CAMPAIGNID:2, t2.CALLS:16
ID:3
t1.CAMPAIGNID:3, t1.TERMCD:Refused, t2.CAMPAIGNID:3, t2.CALLS:32
t1.CAMPAIGNID:3, t1.TERMCD:Refused, t2.CAMPAIGNID:3, t2.CALLS:64
t1.CAMPAIGNID:3, t1.TERMCD:Accepted, t2.CAMPAIGNID:3, t2.CALLS:32
t1.CAMPAIGNID:3, t1.TERMCD:Accepted, t2.CAMPAIGNID:3, t2.CALLS:64
Now it should be clear why you see what you see.
Sum with no constraint:
t1.CAMPAIGNID:3, t1.TERMCD:Refused, t2.CAMPAIGNID:3, t2.CALLS:32
t1.CAMPAIGNID:3, t1.TERMCD:Refused, t2.CAMPAIGNID:3, t2.CALLS:64
t1.CAMPAIGNID:3, t1.TERMCD:Accepted, t2.CAMPAIGNID:3, t2.CALLS:32
t1.CAMPAIGNID:3, t1.TERMCD:Accepted, t2.CAMPAIGNID:3, t2.CALLS:64
Count where a.t1.TERMCD = "Refused"
t1.CAMPAIGNID:3, t1.TERMCD:Refused, t2.CAMPAIGNID:3, t2.CALLS:32
t1.CAMPAIGNID:3, t1.TERMCD:Refused, t2.CAMPAIGNID:3, t2.CALLS:64
I'm not sure what you want to see, but this should at least show you that your output is accurate.
Now that we got that out of the way, your SQL query is below
SELECT DISTINCT A.CAMPAIGNID
, RFJOIN.RF
, CCJOIN.CC
, CALLSJOIN.CALLS
, CALLSJOIN.CALLS / RFJOIN.RF as Calculated
FROM tbl1 A
inner join (SELECT CAMPAIGNID
, count() as RF
FROM tbl1
WHERE TERMCD='Refused'
GROUP by CAMPAIGNID) RFJOIN on RFJOIN.CAMPAIGNID = a.CAMPAIGNID
inner join (SELECT CAMPAIGNID
, count() as CC
FROM tbl1
WHERE TERMCD LIKE '%Con%'
GROUP by CAMPAIGNID) CCJOIN on CCJOIN.CAMPAIGNID = a.CAMPAIGNID
inner join (SELECT CAMPAIGNID
, SUM(CALLS) as CALLS
FROM tbl2
GROUP by CAMPAIGNID) CALLSJOIN on CALLSJOIN.CAMPAIGNID = a.CAMPAIGNID
I would break it into the subqueries then join them together. You can almost copy the SQL syntax this way
Dim RFJ = From t1 In tbl1
Where t1.TERMCD = "Refused"
Group By t1.CAMPAIGNID Into Group
Select New With {CAMPAIGNID, .RF = Group.Count()}
Dim CCJ = From t1 In tbl1
Where t1.TERMCD.Contains("Con")
Group By t1.CAMPAIGNID Into Group
Select New With {CAMPAIGNID, .CC = Group.Count()}
Dim CAJ = From t2 In tbl2
Group By t2.CAMPAIGNID Into Group
Select New With {CAMPAIGNID, .CALLS = Group.Count()}
Dim query = From A In tbl1
Join RFJOIN In RFJ On RFJOIN.CAMPAIGNID Equals A.CAMPAIGNID
Join CCJOIN In CCJ On CCJOIN.CAMPAIGNID Equals A.CAMPAIGNID
Join CALLSJOIN In CAJ On CALLSJOIN.CAMPAIGNID Equals A.CAMPAIGNID
Select New With {A.CAMPAIGNID, RFJOIN.RF, CCJOIN.CC, CALLSJOIN.CALLS, .Calculated = CALLSJOIN.CALLS / RFJOIN.RF}
Dim queryDistinct = query.Distinct()
' or in one big ugly query :)
Dim fullQuery = (From A In tbl1
Join RFJOIN In From t1 In tbl1
Where t1.TERMCD = "Refused"
Group By t1.CAMPAIGNID Into Group
Select New With {CAMPAIGNID, .RF = Group.Count()} On RFJOIN.CAMPAIGNID Equals A.CAMPAIGNID
Join CCJOIN In From t1 In tbl1
Where t1.TERMCD.Contains("Con")
Group By t1.CAMPAIGNID Into Group
Select New With {CAMPAIGNID, .CC = Group.Count()} On CCJOIN.CAMPAIGNID Equals A.CAMPAIGNID
Join CALLSJOIN In From t2 In tbl2
Group By t2.CAMPAIGNID Into Group
Select New With {CAMPAIGNID, .CALLS = Group.Count()} On CALLSJOIN.CAMPAIGNID Equals A.CAMPAIGNID
Select New With {A.CAMPAIGNID, RFJOIN.RF, CCJOIN.CC, CALLSJOIN.CALLS, .Calculated = CALLSJOIN.CALLS / RFJOIN.RF}).Distinct()

It truly is a case of me making it WAY more complicated then it was and not knowing enough to ask the right questions. I wanted to mimic the subquery concept in TSQL but I didn't explain it well. What threw me was the LINQ syntax which seems to always be my downfall with LINQ. I know what I wanted to do I just didn't know how to do it the LINQ way. Thanks to you all who have helped especially #djv.
Dim query =
From t1 In tbl1 Group t1 By t1.CAMPAIGNID Into grp = Group
Join t2 In (From p In tbl2 Group p By p.CAMPAIGNID Into g = Group
Select New With {
.CAMPAIGNID = CAMPAIGNID,
.CALLS = CType(g.Sum(Function(d) d.CALLS), Integer?).GetValueOrDefault(0),
})
On CAMPAIGNID Equals t2.CAMPAIGNID
Select New With {
.CampaignID = CAMPAIGNID,
.RF = CType(grp.Count(Function(b) b.TERMCD = "Refused"), Integer?).GetValueOrDefault(0),
.CALLS = t2.CALLS
}

Related

How resolve a error that a subquery is not introduced with EXISTS?

I am trying to run my query but I get an error.
This is my query:
SELECT DISTINCT
F.FORN_ID,
F.FORN_COD,
F.FORN_DESC,
FORN_CEP,
FORN_CNPJ,
F.PAIS_COD,
F.REGI_COD,
(SELECT TOP 1 CONT_NOME FROM CONT_CONTATOS WHERE CONT_PRINCIPAL = 1 AND SEGM_COD = #SEGM_COD AND CONT_INATIVO = 0 AND FORN_ID IN(SELECT FORN_ID FROM FORN_FORNECEDORES WHERE MSTR_ID = F.FORN_ID)) AS CONT_NOME,
(SELECT TOP 1 CONT_EMAIL FROM CONT_CONTATOS WHERE CONT_PRINCIPAL = 1 AND SEGM_COD = #SEGM_COD AND CONT_INATIVO = 0 AND FORN_ID IN(SELECT FORN_ID FROM FORN_FORNECEDORES WHERE MSTR_ID = F.FORN_ID)) AS CONT_EMAIL,
(SELECT TOP 1 SEGM_COD FROM CONT_CONTATOS WHERE CONT_PRINCIPAL = 1 AND SEGM_COD = #SEGM_COD AND CONT_INATIVO = 0 AND FORN_ID IN(SELECT FORN_ID FROM FORN_FORNECEDORES WHERE MSTR_ID = F.FORN_ID)) AS SEGM_COD,
(SELECT FORN.* FROM FORNECEDORES_PERFIL as FORN
LEFT JOIN PERF_PERFIL as PERFIL
ON FORN.PERF_COD = PERFIL.PERF_COD
LEFT JOIN FAB_FABRICA as FAB ON FORN.FAB_COD = FAB.FAB_COD
LEFT JOIN TIPO_FABRICAS as TIPO_FAB ON FORN.TP_FAB_COD = TIPO_FAB.TP_FAB_COD
WHERE FORN_ID = F.FORN_ID
) AS PROFILE,
--C.CONT_NOME,
--C.CONT_TEL,
--C.CONT_TEL2,
--C.CONT_CEL,
--C.CONT_EMAIL,
--C.SEGM_COD,
F.FEIR_COD,
FE.FEIR_DESC,
F.CREATE_DATE,
F.FORN_STATUS,
F.USU_COD,
(SELECT COUNT(CONT_ID) FROM CONT_CONTATOS WHERE CONT_PRINCIPAL = 1 AND SEGM_COD = #SEGM_COD AND CONT_INATIVO = 0 AND FORN_ID IN(SELECT FORN_ID FROM FORN_FORNECEDORES WHERE MSTR_ID = FORN_ID)) AS COUNT_CONT_PRINCIPAL,
F.PLAT_ID,
F.MSTR_ID,
F.CODE,
(SELECT SEGM_COD FROM FORNECEDORES_FAVORITOS WHERE SEGM_COD = #SEGM_COD AND FORN_ID = F.FORN_ID) AS FAVORITES,
(SELECT COUNT(NOTA_ID) FROM NOTA_NOTAS WHERE SEGM_COD = #SEGM_COD AND TP_NOTA_ID = 2 AND NOTA_INATIVA = 0 AND OBJ_ID = F.FORN_ID) AS NOTA_COUNT,
ROW_NUMBER() OVER(ORDER BY F.FORN_ID) AS LINHA,
F.UPDATE_DATE
FROM FORN_FORNECEDORES F
LEFT OUTER JOIN FEIR_FEIRAS FE (nolock) ON FE.FEIR_COD = F.FEIR_COD
--LEFT OUTER JOIN END_ENDERECOS E ON E.FORN_ID = F.FORN_ID
--LEFT OUTER JOIN CONT_CONTATOS C ON C.FORN_ID = F.FORN_ID AND C.CONT_PRINCIPAL = 1 AND C.CONT_INATIVO = 0
WHERE (F.FORN_DESC like '%'+#FORN_DESC+'%' or #FORN_DESC IS NULL)
AND (F.FEIR_COD = #FEIR_COD or #FEIR_COD IS NULL)
AND (F.FORN_ID = #FORN_ID or #FORN_ID IS NULL)
AND (F.FORN_STATUS = #FORN_STATUS or #FORN_STATUS IS NULL)
AND (F.USU_COD = #USUARIO_ID OR #USUARIO_ID IS NULL)
AND (CONVERT(VARCHAR(10),F.CREATE_DATE,102) >= CONVERT(VARCHAR(10),#CREATE_DATE_I,102)or #CREATE_DATE_I IS NULL)
AND (CONVERT(VARCHAR(10),F.CREATE_DATE,102) <= CONVERT(VARCHAR(10),#CREATE_DATE_F,102) or #CREATE_DATE_F IS NULL)
AND (CONVERT(VARCHAR(10),F.UPDATE_DATE,102) >= CONVERT(VARCHAR(10),#UPDATE_DATE,102)or #UPDATE_DATE IS NULL)
AND FORN_INATIVO = 0
AND F.FORN_ID = F.MSTR_ID
`
the error is exactly when I added this sub query
(SELECT FORN.* FROM FORNECEDORES_PERFIL as FORN
LEFT JOIN PERF_PERFIL as PERFIL
ON FORN.PERF_COD = PERFIL.PERF_COD
LEFT JOIN FAB_FABRICA as FAB ON FORN.FAB_COD = FAB.FAB_COD
LEFT JOIN TIPO_FABRICAS as TIPO_FAB ON FORN.TP_FAB_COD = TIPO_FAB.TP_FAB_COD
WHERE FORN_ID = F.FORN_ID
) AS PROFILE,
I observed some random questions but none of them worked, I even tried to add FORN.* but without success
This error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
It's this subquery in the SELECT clause:
(SELECT FORN.* FROM FORNECEDORES_PERFIL as FORN
LEFT JOIN PERF_PERFIL as PERFIL
ON FORN.PERF_COD = PERFIL.PERF_COD
LEFT JOIN FAB_FABRICA as FAB ON FORN.FAB_COD = FAB.FAB_COD
LEFT JOIN TIPO_FABRICAS as TIPO_FAB ON FORN.TP_FAB_COD = TIPO_FAB.TP_FAB_COD
WHERE FORN_ID = F.FORN_ID
) AS PROFILE,
Each item in the SELECT clause is only allowed to have ONE value. However, the subquery returns FORN.*, which is many values. If you really want to include every column from the subquery in the results, you may try using an APPLY lateral join instead.

LINQ to DATASET with Group Join and Group By (vb.net)

I've got 2 datatables and am trying to summarize the data in them using a left outer join. The join works fine with this code
Dim Journal = From entries In dt.AsEnumerable()
Join inccodes In dtGL.AsEnumerable()
On entries.Field(Of String)("GLCode") Equals inccodes.Field(Of String)("GLCode")
Group By keys = New With {Key .IncomeCode = entries.Field(Of String)("GLCode"), Key .IncomeDesc = .inccodes.Field(Of String)("GLCodeDesc")}
Into ChargeSum = Group, sm = Sum(entries.Field(Of Decimal)("Amount"))
Where sm <> 0
Select New GL_Journal With {.IncomeCode = keys.IncomeCode, .IncomeDesc = keys.IncomeDesc, .LineAmount = sm}
`
However, since I really want a Left Outer Join I want to use Group Join instead of Join.
As soon as I change the Join to Group Join the code in the Group by at ".inccodes.field(Of String)("GLCodeDesc")" has ".inccodes" highlighted with the error "'inccodes' is not a member of 'anonymous type'"
I've reviewed much documentation on Group By and Group Join but there is scant information on them together.
Any ideas? Would I have more options/success with the method syntax?
If i try to reproduce your query using a left outer join, I will do something like this :
Dim dt As New DataTable
dt.Columns.Add("GLCode", GetType(String))
dt.Columns.Add("Amount", GetType(Decimal))
dt.Rows.Add("111", 3251.21)
dt.Rows.Add("222", 125.79)
dt.Rows.Add("999", 10000)
Dim dtGL As New DataTable
dtGL.Columns.Add("GLCode", GetType(String))
dtGL.Columns.Add("GLCodeDesc", GetType(String))
dtGL.Rows.Add("111", "a")
dtGL.Rows.Add("222", "b")
dtGL.Rows.Add("333", "c")
Dim Journal = From entries In dt.AsEnumerable()
Group Join inccodes In dtGL.AsEnumerable()
On entries.Field(Of String)("GLCode") Equals inccodes.Field(Of String)("GLCode")
Into Group
From lj In Group.DefaultIfEmpty()
Group By keys = New With {Key .IncomeCode = entries.Field(Of String)("GLCode"), Key .IncomeDesc = lj?.Field(Of String)("GLCodeDesc")}
Into ChargeSum = Group, sm = Sum(entries.Field(Of Decimal)("Amount"))
Select New With {.IncomeCode = keys.IncomeCode, .IncomeDesc = keys.IncomeDesc, .LineAmount = sm}

LINQ Join tables, group and sum items only if values in stock is 1

I would like to join 4 table, main table in this example is "MAGAZ101" (records on screen).
Table "TOWARY" keep name of items, unit of measurement(kg, quantity), itc.
Table "MAGAZ01" keep info about item in stock (1 in, 0 sold).
Table "PRZYTOW" keep info about how many same items had been take to stock also real weight of item.
Tables "MAGAZ101", "TOWARY", "MAGAZ01" are join by fields "TOWAR".
My problem is join "MAGAZ01" and "PRZYTOW" by column "DOK_PRZYJ", group and sum weight in "PRZYTOW" and also sum stock in "MAGAZ01", sum if item in table "MAGAZ01" is "1".
Here is my Code:
'''''''''
Dim MAGAZYNGLOWNY = (From tab1 In MAGAZ101.AsEnumerable()
Join tab2 In TOWARY.AsEnumerable() On tab1.Field(Of String)("TOWAR") Equals tab2.Field(Of String)("TOWAR")
Join tab3 In MAGAZ01.AsEnumerable() On tab1.Field(Of String)("TOWAR") Equals tab3.Field(Of String)("TOWAR")
Join tab4 In PRZYTOW.AsEnumerable() On tab3.Field(Of String)("DOK_PRZYJ") Equals tab4.Field(Of String)("DOK_PRZYJ")
Select New With {
.Symbol = tab1.Field(Of String)("TOWAR"),
.Nazwa = tab2.Field(Of String)("NAZWA"),
.Jm = tab2.Field(Of String)("JM"),
.Stan = If(IsDBNull(tab3.Item("STANMAG")), 0, tab3.Field(Of Double)("STANMAG")),
.WAGA = If(IsDBNull(tab4.Item("WAGA")), 0, tab4.Field(Of Double)("WAGA"))
}).ToList
Group and sum:
Dim MAGAZYNGLOWNYSUMA = (From A1 In MAGAZYNGLOWNY
Group A1 By Key = New With {.SYMBOL = A1.Symbol, .NAZWA = A1.Nazwa, .JM = A1.Jm, .STAN = A1.Stan, .Waga = A1.WAGA} Into Group
Select New With {
.Symbol = Key.SYMBOL,
.Nazwa = Key.NAZWA,
.Jm = Key.JM,
.Stan = Group.Sum(Function(A) A.Stan),
.WAGA = Group.Sum(Function(A) A.WAGA)
})
.Symbol - ID of item,
.Nazwa - name of item,
.Jm - unit,
.STAN - how many in stock,
.WAGA - weight,
Thanks in advace Adam
If you need, ask for detail.
Here is correct working code.
1st "MAG_GLOW" joined tables 1 and 2.
2nd "dane" joined tables 3 and 4, by "TOWAR" and also "DOK_PRZYJ" in the result the table is sorted and easy to sum.
3rd "Stock" where stock is greater than 0 (sum "STAN") and where stock is greater than 0 (sum weight "WAGA")
4th "MAGAZYNGLOWNY" joined 1st step "MAG_GLOW" and 3rd step "Stock".
Dim MAG_GLOW = (From tab1 In MAGAZ101.AsEnumerable()
Join tab2 In TOWARY.AsEnumerable() On tab1.Field(Of String)("TOWAR") Equals tab2.Field(Of String)("TOWAR")
Select New With {
.TOWAR = tab1.Field(Of String)("TOWAR"),
.Nazwa = tab2.Field(Of String)("NAZWA"),
.Jm = tab2.Field(Of String)("JM")
}).ToList
Dim dane = (From TAB3 In MAGAZ01.AsEnumerable()
Join TAB4 In PRZYTOW.AsEnumerable() On TAB3.Field(Of String)("towar") Equals TAB4.Field(Of String)("towar") And TAB3.Field(Of String)("Dok_przyj") Equals TAB4.Field(Of String)("Dok_przyj")
Select New With
{
.TOWAR = TAB3.Field(Of String)("TOWAR"),
.STAN = If(IsDBNull(TAB3.Item("STANMAG")), 0, TAB3.Field(Of Double)("STANMAG")),
.WAGA = If(IsDBNull(TAB4.Item("WAGA")), 0, TAB4.Field(Of Double)("WAGA"))
})
Dim stock = (From MAG In dane
Group MAG By TOWAR = MAG.TOWAR Into G = Group
Select New With {
.TOWAR = TOWAR,
.Stan = G.Where(Function(x) x.STAN > 0).Sum(Function(x) x.STAN),
.Waga = G.Where(Function(x) x.STAN > 0).Sum(Function(x) x.WAGA)
}
)
Dim MAGAZYNGLOWNY = (From tab1 In MAG_GLOW
Group Join tab2 In stock On tab2.TOWAR Equals tab1.TOWAR Into co = Group
From tab2 In co.DefaultIfEmpty()
Order By tab1.TOWAR
Select New With
{.TOWAR = tab1.TOWAR,
.NAZWA = tab1.Nazwa,
.Jm = tab1.Jm,
.STAN = If(IsNothing(tab2), Nothing, tab2.Stan),
.WAGA = If(IsNothing(tab2), Nothing, tab2.Waga)
})

LINQ, Join, Group By and SUM

In this VB.NET query, how can I get access to the fields in the new statement?
Dim query =
From t1 In tbl1
Join t2 In tbl2 On t1.CAMPAIGNID Equals t2.CAMPAIGNID
Group By t1.CAMPAIGNID Into Group
Select New With {
.id = CAMPAIGNID,
.CALLS = Group.Sum(Function(a) t2.CALLS),
.count = Group.Count(Function(a) t1.TERMCD = "Refused")
}
You can access the fields via the passed in parameter a. The parameter a is of the anonymous type you created via New With {...}
Dim query =
From t1 In tbl1
Join t2 In tbl2 On t1.CAMPAIGNID Equals t2.CAMPAIGNID
Group By t1.CAMPAIGNID Into Group
Select New With {
.id = CAMPAIGNID,
.CALLS = Group.Sum(Function(a) a.t2.CALLS),
.count = Group.Count(Function(a) a.t1.TERMCD = "Refused")
}

Convert SQL Query to LINQ query/Lambda expression

I am trying to fetch the results from the DB using the Entity Framework using the below SQL query:
SELECT
Header_Id,
Header_Number, Details_Id,
Details_Header_Date,
(SELECT TOP 1 c.[Comment_Description] FROM [Comment] c
WHERE c.[Comment_CarrierId] = i.[Header_CarrierId] AND c.[Comment_ParentEntityId] = i.[Header_Id]
ORDER BY c.Comment_AddedOn DESC) AS 'HeaderComments',
CONCAT(ht.[HeaderTracker_Reason], ' ', ht.[HeaderTracker_Notes]) AS 'RejectedComments',
at.[InternalComments] AS 'InternalComments',
CASE i.[Header_Status]
WHEN 'Pending' THEN ar.[HeaderTracker_ApprovedLvl] END AS 'ApprovedLevel',
CASE i.[Header_Status]
WHEN 'Pending' THEN ar.[HeaderTracker_DueBy] END AS 'ApprovedDueDate'
FROM [Header] i
LEFT OUTER JOIN [Details] ii
ON i.[Header_Id] = ii.[Details_HeaderId]
INNER JOIN [Carrier] t
ON t.[Carrier_Id] = i.[Header_CarrierId]
LEFT OUTER JOIN [HeaderTracker] ht
ON ht.[HeaderTracker_HeaderId] = i.[Header_Id] AND ht.[HeaderTracker_Type] = 'Rejected'
LEFT OUTER JOIN [AdjustmentTracker] at
ON at.[DetailsId] = ii.[Details_Id]
LEFT OUTER JOIN [HeaderTracker] ar
ON ar.[HeaderTracker_HeaderId] = i.[Header_Id]
AND i.[Header_Status] IN ('Paid', 'Pending', 'Approved', 'PaidWithAdj')
AND ar.[HeaderTracker_IsPending] = 1
The result output should be using LINQ query / LAMBDA expression
The following code is what I tried: (not sure how TOP 1 and CASE would come here + if & is also valid here)
var statuses = new string[] { "Paid", "Pending", "Approved", "PaidWithAdj" };
var hdrdet =
(
from hdr in dbContext.Headers
join det in dbContext.Details on hdr.Header_Id equals det.Header_Id into hdrdet
from h in hdrdet.DefaultIfEmpty()
join carr in dbContext.Carriers on hdr.Carrier_Id equals carr.Header_Carrier_Id into carrs
from c in carrs.DefaultIfEmpty()
join hdrtk in dbContext.HeaderTracker on hdr.Header_Id equals hdrtk.HeaderTracker_HeaderId && hdrtk.HeaderTracker_Type equals "Rejected" into hdrtks
from k in hdrtks.DefaultIfEmpty()
join adjt in dbContext.AdjustmentTracker on adjt.DetailsId equals det.Details_Id into adjts
from a in adjts.DefaultIfEmpty()
join pnd in dbContext.HeaderTracker on pnd.HeaderTracker_HeaderId equals hdr.Header_Id && hdr.Header_Status contains(statuses) && pnd.[HeaderTracker_IsPending] equals 1 into pnds
from p in pnds.DefaultIfEmpty()
select new
{
hdrid = Header_Id,
hdrnumber = Header_Number, Details_Id,
det_date = Details_Header_Date,
reason = HeaderTracker_Reason + ' ' + HeaderTracker_Notes,
intcomments = InternalComments
}
)