Multiple columns in Linq left outer join - vb.net

Could somebody help me complete this linq left outer join query so that the second column of the right table (tempData) is contained in the result set even though it may be null?
sortedData = From cs In mbCustomSort
Order By cs(0)
Group Join entry In tempData On cs(joinColumn) Equals entry(0) Into Group
From last In Group.DefaultIfEmpty _
Select New With {.groupField = cs(joinColumn)}

Sorry, I write in C#, but how about:
var sortedData = from cs in mbCustomSort orderby cs.JoinColumn
join entry in tempData on cs.JoinColumn equals entry.OtherJoinColumn into Group
from subentry in Group.DefaultIfEmpty()
select new { groupField = cs.JoinColumn };

LINQPad's default processing doesn't allow for item(fieldno), so I used actual field names in data repurposed from here, including adding a new row in Mbc with no corresponding OrderId in Mbtd. This works for me:
From cs In Mbcs _
Order By cs.Catalogid _
Group Join entry In mbtds On cs.OrderId Equals entry.OrderId Into Group _
From last In Group.DefaultIfEmpty _
Select cs.OrderId, last.Ocardtype
And by "works" I mean the row I added appears with a null Ocardtype (as well as another row where Ocardtype was already null).

(Edited)
The From last In Group turns the outer join into an inner join. This does not happen when you continue with the Group variable:
sortedData = From cs In mbCustomSort
Order By cs(0)
Group Join entry In tempData On cs(joinColumn) Equals entry(0) Into Group
Select New With {.groupField = cs(joinColumn),
.col2 = Group(1).RightColumn }
Change RightColumn by the property of "In-memory Query" object.

Related

Adding a WHERE clause to a Group Join

I am working in VB.NET. I have two datatables (table & table2), which are identical. The two columns in question are:
id | voided_id
1 | null
2 | null
3 | 2
table1 is the list of items, and table2 is the list of voided items. so, if an item has voided an earlier item, I want to exclude the voided item. In this example id 2 would be excluded because it was voided by id 3.
Here is what I have so far:
Dim compareResults = From table In resultOds
Group Join table2 In voidOds
On table.Field(Of Int64)("id") Equals table2.Field(Of Int64?)("voided_loan_id")
Into tablesJoin = Group From tableJoin In tablesJoin.Where(Function(x) x.Field(Of Int64?)("voided_loan_id") Is Nothing).DefaultIfEmpty()
Select table
right now, I get everything. The WHERE clause inside the group join isn't working. Any suggestions?
Many articles I found said .DefaultIfEmpty() should provide the functionality of the WHERE but this returns everything as well:
Dim compareResults2 = From table In resultOds
Group Join table2 In voidOds
On table.Field(Of Int64)("id") Equals table2.Field(Of Int64?)("voided_loan_id") Into tablesJoin = Group
From table2 In tablesJoin.DefaultIfEmpty()
Select table
based on some off-line input I got, I rewrote this as a subquery. Still returns everything.
Dim compareResults2 = From r In resultOds
Where Not (From v In voidOds Where v.Field(Of Int64?)("voided_loan_id") IsNot Nothing Select v.Field(Of Int64?)("voided_loan_id")).Contains(r.Field(Of Int64?)("id"))
Select r
Try below
C#
var s =ItemTable.Where(i=>!VoidedItem.Any(v=>v.id==i.id))?.ToList();
VB
Dim s = ItemTable.Where(Function(i) Not VoidedItem.Any(Function(v) v.id = i.id))?.ToList()
I didn't get it working so I defaulted to executing a SQL string. thanks for the feedback.

LINQ: How can I Join to child table using data from group join?

I have to expand upon an existing query in one of the applications I'm working on.
Table relationships are as follows:
tableName relationship tableName2 Join columns
title 1:1 parcel p_id:p_id
title 1:many transaction title_no:new_title_no
transactions many:1 title old_title_no:title_no
The query is essentially a data loader to reduce the number of round trips to the database.
The existing query looks like this:
From title In context.Title
Join parcel In context.Parcel
On title.p_id Equals parcel.P_Id
Group Join transaction In context.Transaction
On title.title_no Equals transaction.New_Title_No And title.transfer_date Equals transaction.Transfer_Date Into transactions = Group
Select New TitleSearchResult() With {.Title = title, .Pc_Parcel = parcel, .Transactions = transactions}
Which returns a custom data type to store the different values.
The application also maps these values(the Title entity contains unmapped properties to store the data from the other entities) :
For Each result In query
result.Title.Parcel = result.Parcel
result.Title.Transactions = result.Transactions.ToList()
Next
I need to return the title associated with each transaction based on old_title_no.
I've tried to break the queries up as follows:
Dim query1 = From title In context.Title
Join parcel In context.Parcel
On title.p_id Equals parcel.P_Id
Select title, parcel
Dim query2 = From title_old In context.Title
Join trans As Transaction In context.Transaction
On title_old.title_no Equals trans.Old_Title_No
Select trans, title_old
Dim query3 = From b In query1
Group Join c In query2
On b.title.title_no Equals c.trans.New_Title_No And b.title.transfer_date Equals c.trans.Transfer_Date
Into transactions = Group
Select b.title, b.parcel, transactions
Which seems to do the right querying, but doesn't allow me to create a new TitleSearchResult object like the following (because I can't break out the data from the transaction object):
From t In query3.ToList()
Select New TitleSearchResult() With {.Title = t.title, .Pc_Parcel = t.parcel, _
.Transactions = t.transactions.trans, .Old_Titles = t.transactions.title_old}
How can I still do the group join on transaction (because I need the IEnumerable returned so that I can use it in another query on the database) and be able to separate the trans and title_old objects?
Assuming the TitleSearchResult has List types for Old_Titles and Transactions, you can do:
var ans = From t In query3.ToList() _
Select New TitleSearchResult() With {
.Title = t.title,
.Pc_Parcel = t.parcel,
.Transactions = t.transactions.Select(Function(t1) t1.trans).ToList(),
.Old_Titles = t.transactions.Select(Function(t1) t1.title_old).ToList()
}

VB Linq Group Join query FAILS to order the results in descending order

Has anyone got any clue why this query fails to order the results by descending VisitStart order, despite the two OrderBy clauses in the query?
The term "ΗμΏραΕπίσκεψης" is the "VisitStart" in Greeks!!
The two OrderBy clauses are placed because I desperately need to order the results by this VisitStart column in descending order!
Also, is it possible to replace the "null" result in the last column cells with either 0 (zero) or "" (empty string)?
(From p In Patients
Join v In Visits On v.Patient Equals p
Join t In VisitTypes On v.VisitType Equals t
Group Join m In Payments On m.Visit Equals v Into PaymentsGroup = Group, g = sum(Ctype(m.Ποσό, Integer?))
Order By v.VisitStart Descending
From pmnt In PaymentsGroup.DefaultIfEmpty()
Where
v.VisitStart.Year = 2017
Select New With {
.VId = v.Id,
.PId = v.PatientId,
.Όνομα = p.Όνομα,
.ΗμΏραΕπίσκεψης = v.VisitStart,
.PtFirstVisitEver = p.Added,
.Κόστος = v.Κόστος,
.Πληρωμές = g
}).OrderByDescending(Function(x) x.ΗμΏραΕπίσκεψης).Distinct
Please find the corresponding image of the results here
The Distinct method could alter the order of the list. Therefore, if the order matters, you should do that last just to be safe. In other words:
x.Distinct().OrderByDescending(Function(x) x.ΗμΏραΕπίσκεψης)
Instead of:
x.OrderByDescending(Function(x) x.ΗμΏραΕπίσκεψης).Distinct()

vb.net LINQ LEFT JOIN

I want query LINQ to LEFT JOIN TWO TABLES get results like SQL exactly
(show results like the picture even the row empty yellow line)
My code:
Dim qJoint = From tSum In lstSUM Group Join tbnk In lstBank On tbnk.ID_BANK Equals tSum.ID_BANK _
Into tResult = Group From tbnk In tResult.DefaultIfEmpty Select tbnk.ID_BANK, tbnk.ABRIGER, tbnk.NomBank_AR, tSum.Montant_Facture
Little Problem Try Code:
Dim result= from v in VW_sum_bybank
join b in tbl_bank on v.id_bank equals b.id_bank into jj from kk in jj.DefaultIfEmpty()
select
V_id_bank=v.id_banl,
Code_bank=v.Code_bank,
NOMBANK=v.NOMBANK,
ABRG=v.ABRG,
b_id_bank=kk.ID_bank,
sommeFAC=kk.sommeFAC

VB.NET LINQ to XML Left Join with ambiguous column name

I need to write a LINQ TO XML query, which queries two XML files exported from Access database tables. The original Access DB query looks like this:
SELECT
(
[TableB].[Code] Is Null,[TableA].[Code],
LCase(Left([TableA].[Code],1)) & ":" & [TableB].[code]
) AS Code,
Trim
(
[TableB].[Description] & " " & [TableA].[Description]
) AS Description
FROM TableA LEFT JOIN TableB
ON TableA.Code = TableB.SubProduct;
When I convert it to LINQ to XML, I have the problem of the right part of the left join is not available. My LINQ look like this:
Dim results = _
From a In TableA.Descendants("Product")
Group Join b In TableB.Descendants("Product")
On a.Element("Code").Value Equals b.Element("SubProduct").Value Into leftJoinGroup Group
From p In leftJoinGroup.DefaultIfEmpty
Select New With
{
I DON KNOW HOW TO WRITE IT
}
Both tables have the column named "Code". However, the variable TableB seems to be unavailable inside my Selectclause. I only have a and p available so I can't get the Code from TableB (b). How should I do that?
I just started using linq myself and ran into this issue last week. This was very helpful for me http://msdn.microsoft.com/en-us/vstudio/bb688088.aspx but here is an example of how to perform a left outer join in vb.net http://msdn.microsoft.com/en-us/vstudio/bb737909#lojoin.
In your example tableB is being stored into leftJoinGroup which your selecting from using p. To get values from tableB you will need to select from p and since your trying to concatenate the columns from both tableA and tableB, I would check if tableB record is null.
Dim results = From a In TableA.Descendants("Product") Group Join b In TableB.Descendants("Product") _
On a.Element("Code").Value Equals b.Element("SubProduct").Value Into leftJoinGroup = Group _
From p In leftJoinGroup.DefaultIfEmpty() _
Select New With { _
.Code = If(p Is Nothing, a.Element("Code").Value, String.Format("{0}:{1}", Left(a.Element("Code").Value.ToLower(), 1), p.Element("Code").Value)), _
.Description = If(p Is Nothing, a.Element("Description").Value, String.Format("{0} {1}", p.Element("Description").Value, a.Element("Description").Value))}
Here is an example of your code above, I didn't tested it. I've used this code when joining datatables not xdocuments. Sorry if this isn't clear this my first post here.