LINQPad Screenshot where TAanlysis is T2 table which I can expand to see details.
I have four tables. Three of them need to join with left while two of them with inner join.
Here is the SQL code that I'm trying to re-code within LINQ:
select t1.*,t2.*,t3.*
from t1
left outer join t2 on t1.column1=t2.column1
left outer join t3 on t2.column1=t3.column1
INNER join t4 on t2.column1=t4.column1
where t3.column2=x**
Can anyone help how to write such query in LINQ?
I tried below LINQ query in .NET which is yielding different SQL query at backend:
from prsn in db.T1
join co in db.T2 on prsn.Id equals co.Id into ps1
from y1 in ps1.DefaultIfEmpty()
join tproject in db.T3 on y1.Id equals prod.Id into ps2
from y2 in ps2.DefaultIfEmpty()
join res in db.T4 on y1.Id equals res.Id
where y2.ID == x
select prsn;[![enter image description here][1]][1]
SQL query formed at backend:
select filter1.*
from (Select t1.* from t1 inner join t2 on t1.Id=t2.Id
left outer join t3 on t2.Id = t3.Id)as filter1
inner join t4 on filter1.Id= t4.Id
where filter1.Id= x
I tried above LINQ query in .NET which is yielding different SQL query at the backend. Let me know if I am missing anything?
Note : selection of all columns from 3 tables.
Related
I am not trying to join my table using left outer join in LINQ where one of my join conditions does not satisfy. How can I still get the default record in my dataset? My SQL query runs perfectly fine but my join query is not returning the data.
Below is my SQL query where my left outer join works fine:
select
w.issueid as Issue
from worklog w
join jiraissue as j on w.issueid=j.ID
join issuetype AS ty ON ty.ID = j.issuetype
join project AS p on p.ID=j.PROJECT
left outer join customfieldvalue cfv on cfv.ISSUE = w.issueid
Below is my LINQ query in C# where if cfv.issue in the last join is not available in the table, I want to still return the default column.
var data = (from w in worklogs
join i in issuetypes on j.issuetype equals i.ID
join p in projects on j.PROJECT equals p.ID into table0
from c in table0.DefaultIfEmpty()
join cfv in customfieldvalues on w.issueid equals cfv.ISSUE into table1
from d in table1.DefaultIfEmpty()
{
IssueKey = l.Key.pkey + '-' + l.Key.issuenum,
Hours = l.Sum(w => w.timeworked)
}).ToList();
Any help is appreciated.
Thank you.
I am trying to use the "into" statement with DefaultIfEmpty() for the left outer join, but when I try to join to the 3rd collection, it doesn't like it (can't see /use it / find it )
It doesn't seem to like personRole on the line below
join roleTypes in roles on personRole.ContactRoleTypeId equals roleTypes.ContactRoleTypeId into r2
the query:
findPersonResultsViewModelNew =
from azed in findPersonViewModel.findPersonResultsViewModel
join personRole in personContactRoles on azed.PersonID equals personRole.PersonId into r1
join roleTypes in roles on personRole.ContactRoleTypeId equals roleTypes.ContactRoleTypeId into r2
from p in r1.DefaultIfEmpty()
from g in r2.DefaultIfEmpty()
select
//…. other code
Change the order of your statements. When doing left join, you must immediately follow the join with a new from...DefaultIfEmpty():
findPersonResultsViewModelNew =
from azed in findPersonViewModel.findPersonResultsViewModel
join personRole in personContactRoles on azed.PersonID equals personRole.PersonId into prj
from personRole in prj.DefaultIfEmpty()
join roleTypes in roles on personRole.ContactRoleTypeId equals roleTypes.ContactRoleTypeId into rtj
from roleTypes in rtj.DefaultIfEmpty()
select
I can't find a good example, probably I'm searching wrong:
I have a bunch of tables joined via expression syntax and I'd like to left outer join two more, if there are values, otherwise return NULL.
So the sql is looking like this:
select *
from table1 mr
left outer join table2 on table1
left outer join table3 on table2
left outer join table4 on table3
where mr.id = 1234
So a left join is no problem with the syntax like this:
join oiA in query1 on organisation.Id equals oiA.Organisationid into qOrgInhA
from oiA in qOrgInhA.DefaultIfEmpty()
But as soon as I add the other tables depending on the oiA, the Entity Framework produces a Cross-Join, and not a second left outer join.
From what I've read, GroupJoin might be the solution, but I really can't find a good example, the most examples I found have just 2 tables.
Or am I doing something totally wrong?
In method syntax, multiple left joins can be done like this:
var result = table1
.GroupJoin(table2, o => o.Key, i => i.FKey, (t1, t2) => new
{
t1,
t2.GroupJoin(table3, o => o.Key, i => i.FKey, (_t2, t3) => new
{
_t2,
t3
})
});
The resulting query produced by entity framework will be similar to:
select * from table1
left outer join table2 on table1.Key = table2.FKey
left outer join table3 on table2.Key = table3.FKey
Edit:
I'm a bit shaky on query syntax, but its the same idea of doing the second join within the select:
var result = from t1 in table1
join t2 in table2 on t1.Key equals t2.FKey into joinresult
select new
{
t1,
from jr in joinresult
join t3 in table3 on jr.Key eq t3.FKey into joinresult2
select new
{
jr,
joinresult2
}
}
This question already has answers here:
Left outer join in linq
(4 answers)
Closed 8 years ago.
I have a sql query which has innerjoin and leftouter join's which is very tricky to mr to convert to LINQ.
SELECT project.ID, project.No, project.Name,
APPLN.Id,APPLN.Name,SAR.Name
FROM Phasefact phase WITH (NOLOCK)
INNER JOIN AProject project WITH (NOLOCK) on phase.Id = project.ID
INNER JOIN Application APPLN WITH (NOLOCK) ON project.AppId = APPLN.Id
LEFT OUTER JOIN Master master WITH (NOLOCK) ON phase.amId = master.Id
INNER JOIN Ref SAR WITH (NOLOCK) ON SAR.ID = master.Ref_Id
WHERE phase.ID = 123
It is bit confusing as it contains "left outer join". Someone please help.
Maybe something like this:
var result=(
from phase in db.Phasefact
join project in db.AProject
on phase.Id equals project.ID
join APPLN in db.Application
on project.AppId equals APPLN.Id
//Left join
from master in db.Master
.Where(a=>a.Id==phase.amId).DefaultIfEmpty()
join SAR in db.Ref
on SAR.ID equals master.Ref_Id
where phase.ID == 123
select new
{
project.ID,
project.No,
project.Name,
APPLN.Id,
APPLN.Name,
SAR.Name
}
);
EDIT
But i don't get the left join. Why are you using a left join? To me it looks like you first use a left join:
LEFT OUTER JOIN Master master WITH (NOLOCK) ON phase.amId = master.Id
And the after that you have a join that limits the result like this:
INNER JOIN Ref SAR WITH (NOLOCK) ON SAR.ID = master.Ref_Id
This will be the same as doing this:
INNER JOIN Master master WITH (NOLOCK) ON phase.amId = master.Id
INNER JOIN Ref SAR WITH (NOLOCK) ON SAR.ID = master.Ref_Id
I am giving you an basic idea of left outer join in LINQ
var lines = from p in db.Phasefact
join m in db.Master on m.Id equals
p.amId into p_m
where p.ID == 123
from m in p_m.DefaultIfEmpty()
select new { p.ID };
Now you can convert this much more according to your logic... or Query.......
This is a two part question and for education purposes rather than trying to find a solution to a problem.
I've seen this already and realize that it's very similar to my question
LINQ2SQL - Cross join emitted when I want inner join
But I am hoping for more information from you LINQ and SQL gurus as to why the cross join is created instead of inner join in LINQ2SQL. Additionally, can someone explain how SQL Server decides on the execution plan (or link to further information) since both of these queries generate the same plan? From what I understand, this means that the performance of the queries are the same.
I've created a small example that runs two LINQ expressions on my database that generates these two different SQL queries.
For those who don't want to bother, here's my example db diagram:
http://dl.dropbox.com/u/13256/Screen%20shot%202011-03-16%20at%2011.41.56%20AM.png
Here are the two queries:
Cross Join with Where Clause
var q = from item in context.Items
join i_mem in context.Memberships on new { item_id = item.ID, user_id =
current_user_id.Value } equals new { item_id = i_mem.RelatedItemID, user_id =
i_mem.RelatedUserID } into sq_i_m
from im in sq_i_m.DefaultIfEmpty()
join i_cat in context.Categories on item.RelatedCategoryID equals i_cat.ID
into sq_i_cat
from proj in sq_i_cat
select item;
Inner Join
from item in context.Items
join i_mem in context.Memberships on
new { item_id = item.ID, user_id = current_user_id.Value }
equals
new { item_id = i_mem.RelatedItemID, user_id = i_mem.RelatedUserID }
into sq_i_m
from im in sq_i_m.DefaultIfEmpty()
join i_cat in context.Categories on item.RelatedCategoryID equals i_cat.ID
select item
And here is the test program if you'd like to see for yourself.
Thanks for everyone's help.
Mustafa
They are the same thing, so it does not matter which LINQ2SQL emits.
An inner join is logically equivalent to a cross join with a where clause filter equivalent to the on of the inner join clause.
That's why Sql Server generates the same query plan.
To be clear, the inner join:
Select f1
From T1 inner join T2 on T1.k = T2.k
where T1.f2 like 'X%'
Is the same as the cross join:
Select f1
From T1 cross join T2
where T1.k = T2.k
and T1.f2 like 'X%'
is the same as old-style SQL:
Select f1
From T1, T2
where T1.k = T2.k
and T1.f2 like 'X%'
Lets say you have a datacontext called MyDataContext.
using(MyDataContext db = new MyDataContext())
{
var q = db.Items.Where(x=> x.Categories.Name == "myCategory").Select(x=> x);
}
This is a very simple example, but you didn't need to write out a join or a subquery in TSQL syntax. (I hate writing TSQL).