Re: SQL to Linq - Left, Right and Inner Joins
- From: "Frans Bouma [C# MVP]" <perseus.usenetNOSPAM@xxxxxxxxx>
- Date: Sat, 05 Jul 2008 12:50:07 +0200
Michel Walsh wrote:
If used alone, yes, but with a WHERE clause, MS SQL Server optimizer should recognize an (implicit) inner join and thus, limit the effective amount of data transferred through the wire.
That's not what makes it inefficient. The cross-join execution path is often less ideal as the cross-join action by itself is first handled, and THEN the where clause is handled to filter out rows you don't want. As a cross-join can spawn millions of tuples, which are often not needed, the where clause will run slower than an ON clause in an inner-join set operation.
It's not the data that's sent over the wire, it's the query execution itself which makes it less ideal. That's also why I find it a big design flaw in linq that the only operator in the linq's join clause is an 'equals' operator, which makes the production of left/right joins awkward, yet these operations are often required. The alternative is a nested from but that leads to lesser ideal queries than a left-join + accompanying on clause.
FB
Vanderghast, Access MVP
By the way, a natural inner join between {a, a, b} and { a, a, c} returns 4 rows, not 5. My mistake.
"Frans Bouma [C# MVP]" <perseus.usenetNOSPAM@xxxxxxxxx> wrote in message news:uJjrL1a3IHA.1808@xxxxxxxxxxxxxxxxxxxxxxxKeep in mind that:
var q = from a in ctx.A
from b in ctx.B
...
results in a cross-join which could be very inefficient.
FB
Michel Walsh wrote:In fact, you don't do SQL-joins at all, not directly. What you do is using a for-each based representation of the universe which will be TRANSLATED to an expression tree which will be TRANSLATED to an SQL statement. At least, for me, that helps to see the process as being a double translation, and to STOP thinking in SQL sets, while using LINQ, but to then think in terms of for-each sequences.
Side note about the supplied URL: an SQL join is not represented correctly by a Venn diagram since, like an electronic Op-Amp, an SQL join can selectively 'amplify' the number of rows from the original sets. If you make an inner (equi) join between { a, a, b} and { a, a, c}, you end up with 5 rows, something the Venn diagram misses. The Venn diagrams are only applicable if there is no 'duplicated' elements involved in common to both sets ( { a, a, b} and { c, d, d} are ok for a Venn diagram, since no dup appears in common to both sets).
So, for the sequence thing:
-------------
LINQ: from a in b
is to be compare to
foreach( a in b)
and will generate SQL like "FROM b AS a"
------------------
The sequence:
from a in b
from c in d
is a kind of imbricated:
foreach( a in b)
{
foreach ( c in d)
}
and could generate the SQL part:
FROM b AS a, d AS c
---------------------------
While SQL joins explanation (can) start from a cross join, LINQ joins start form a group join.
from a in b
join
c in d
on
a.field equals c.otherField
into newSet
The second 'table' is introduced with the keyword join rather than with the keyword from, as previously, (probably to allow) the on keyword introduces the relation, always an equality (equals is a keyword).
There is no direct SQL equivalence for that. Also note that "a" variable must be at the left of the word equals while "c" variable must be at the right of that keyword. Literature sometimes speaks of left and right side (of equals), but that has nothing to do with SQL LEFT JOIN or SQL RIGHT JOIN.
The result is somehow described as: for each value from b, **link** to it all the values from d satisfying the relation field = otherField. There is no direct SQL statement for that since it is not targeting a 'rectangular' representation of the data.
-------------------------------
To get the SQL INNER JOIN, removes the
into newSet
-------------------------------
To get the SQL LEFT outer join, we can expand the LINQ group join, but for "a" values having no match, we introduce nulls on the unpreserved side, like this:
from a in b
join
c in d
on
a.field equals c.otherField
into newSet
from x in newSet.DefaultIfEmpty()
newSet can be any name you want which do not collide with keyword or other variables.
That is a little bit as saying: if a row in b has disappeared, re-introduce it supplying null (default) for the unpreserved side, and now, the 'alias' to use to refer to the unpreserved side is x.
------------------------------
There is no LINQ-Right outer join, or LINQ-full outer join.
--------------------------
You can use sub-query, here, in the SQL-select clause:
LINQ:
from a in b
select new { ..., someName = { from c in d ... select something} }
SQL:
SELECT... (SELECT something FROM d AS c ... ) AS someName
-------------------------
We can cascade the queries:
var query1 = from ... ;
var query2 = from query1 ... ;
which can be used too if you need complex outer join, for your SQL statement.
------------------------------
For non-equi join, I suggest you start with a cross join and add the required where clause. That won't do much for outer non equi join, though.
-------------------------------
You can use direct to SQL with ExecuteQuery<T> method accepting the SQL statement as a string.
-------------------------------
There is much more to it.
-------------------------------
Note that I didn't include a SELECT clause in many of the examples: you have to, in order to make a valid statement.
Hoping it may help,
Vanderghast, Access MVP
"shapper" <mdmoura@xxxxxxxxx> wrote in message news:1f6a18e9-998a-4ff1-95f4-b1a0b90da256@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxHello,
I am used to SQL but I am starting to use LINQ.
How can I create Left, Right and Inner joins in LINQ? How to
distinguish the different joins?
Here is a great SQL example:
http://www.codinghorror.com/blog/archives/000976.html
Thanks,
Miguel
--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
.
- Follow-Ups:
- Re: SQL to Linq - Left, Right and Inner Joins
- From: Michel Walsh
- Re: SQL to Linq - Left, Right and Inner Joins
- From: Jon Skeet [C# MVP]
- Re: SQL to Linq - Left, Right and Inner Joins
- References:
- SQL to Linq - Left, Right and Inner Joins
- From: shapper
- Re: SQL to Linq - Left, Right and Inner Joins
- From: Michel Walsh
- Re: SQL to Linq - Left, Right and Inner Joins
- From: Frans Bouma [C# MVP]
- Re: SQL to Linq - Left, Right and Inner Joins
- From: Michel Walsh
- SQL to Linq - Left, Right and Inner Joins
- Prev by Date: Re: Using ref
- Next by Date: Re: Open Outlook on user machine
- Previous by thread: Re: SQL to Linq - Left, Right and Inner Joins
- Next by thread: Re: SQL to Linq - Left, Right and Inner Joins
- Index(es):
Relevant Pages
|