SELECT LEFT JOIN (SELECT)

Posts   
 
    
hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 23-May-2011 13:15:27   

Here is a mysql query to get most recent orders for all employees


SELECT
e.EmployeeID,
v.OrderID, v.OrderDate
FROM Employees e  
LEFT JOIN
        Orders v
ON    v.OrderID = 
        (
        SELECT  OrderID
        FROM    Orders vi
        WHERE   vi.EmployeeID = e.EmployeeID
        ORDER BY
                vi.OrderDate DESC, vi.EmployeeID DESC
        LIMIT 1
        );

How to do this in llblgen Linq?

Here is where i'm now:


            var e = from ee in md.Employee
                    join o in md.Order on
                    (
                        from ox in md.Order
                        where ee.EmployeeId == ox.EmployeeId
                        orderby ox.OrderDate descending, ox.EmployeeId descending
                        select ox.OrderId
                    ).First() equals o.OrderId into outer
                    from oy in outer.DefaultIfEmpty()
                    select new { ee.EmployeeId, oy.OrderId, oy.OrderDate };

But the resulting query is completely wrong, apparently the inner predicates are being ignored or something.

Thanks. Hugo

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 23-May-2011 15:28:59   

Would this simplified query give the same results?

SELECT
e.EmployeeID,
MAX(v.OrderID), MAX(v.OrderDate)
FROM Employees e 
LEFT JOIN Orders v ON v.EmployeeID = e.EmployeeID
Group By e.EmployeeID

Assuming OrderID is inremental.

hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 23-May-2011 15:59:15   

Hi Walaa,

Thanks for fast reply.

In this scenario, yes, the result is the same, but if I want to select any other fields from Orders table, like ShipCountry? This is my problem.

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 23-May-2011 16:05:59   

So the above SQL returns a table of EmployeeId and their latest OrderId. Using the OrderId you join to the Order table to get rest of fields.

hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 24-May-2011 13:07:41   

Maybe my initial question was not clear about my intentions, my main objective is to understand how to perform correlated subqueries (where the subquery is dependent from the top query) in LLBLGen Linq Provider.

This kind of queries are really handy to solve day to day tasks.

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 24-May-2011 18:52:36   

Could you post the incorrectly generated SQL from your original query, and an example of how you would expect the SQL to look. This will give us a better idea of what you are trying to acheive.

Thanks

Matt

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 25-May-2011 11:00:16   

Correlated subqueries aren't defined directly in linq. You define the correlation implicitly in Linq by simply referencing the related element in a where clause for example. The correlated subquery is then created for you (if necessary).

If you want explicit control over when a correlated subquery is created, please take a look at our new query api system QuerySpec, which is in beta now for v3.0/v3.1 (customer area), or use our (more low level) query system and define the predicates (FieldCompareSetPredicate) with the correlated subquery manually.

Frans Bouma | Lead developer LLBLGen Pro
hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 25-May-2011 15:53:24   

Hello Frans,

I read in your blog about QuerySpec and it looks very promising, so far we are on v2.0 but we may consider an upgrade to v3.

Can you provide me the correct Linq code to perform the query from my initial post?

Thanks in advance, Hugo

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 25-May-2011 16:20:19   

so far we are on v2.0 but we may consider an upgrade to v3.

v.2.0, That's a very valuable piece of information. simple_smile I assumed you were using v.3.1

Could you please specify which runtime library version are you using?

hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 25-May-2011 17:04:15   

Sorry about not being so clear:

.NET 3.5 and LLBLGen Pro 2.0:

SD.LLBLGen.Pro.LinqSupportClasses.NET35.dll v2.6.9.407 SD.LLBLGen.Pro.ORMSupportClasses.NET20.dll v2.6.9.305

Hugo

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 25-May-2011 17:40:29   

That's 2.6 not 2.0 simple_smile Anyway it seems you have an old runtime library.

Would you please downlowad the latest release of v.2.6 and try again.

hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 26-May-2011 20:45:19   

Better yet, I'm using (evaluating) v3.1 now simple_smile

Unfortunately I have the same problem, can't create that query. Any example?

MTrinder
User
Posts: 1461
Joined: 08-Oct-2008
# Posted on: 26-May-2011 21:26:15   

Sorry to point you to another site rather than answer your question directly, but stackoverflow these days seems to come up first in almost any google search about a code query... simple_smile

Does either of these threads point you in the right direction?

http://stackoverflow.com/questions/2225052/is-it-possible-to-create-a-correlated-subquery-in-linq

http://stackoverflow.com/questions/4248193/convert-sql-query-with-correlated-subquery-to-linq-in-c

Matt

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39908
Joined: 17-Aug-2003
# Posted on: 27-May-2011 12:34:35   

ALso, what's the SQL query being generated from the linq query you've formulated in the starting post?

Frans Bouma | Lead developer LLBLGen Pro
hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 27-May-2011 12:59:37   

Hi MTrinder,

I think your suggestions pointing me in the write path! I got what I want now.

Here is the my final and WORKING linq query:


            var e = from ee in md.Employee
                    join o in md.Order on ee.EmployeeId equals o.EmployeeId into outer
                    from o in outer.DefaultIfEmpty()
                    where o.OrderId == (from oo in md.Order
                                        where oo.EmployeeId == ee.EmployeeId
                                        orderby oo.OrderDate descending
                                        select oo.OrderId).First() || o.OrderId == null
                    select new { ee.EmployeeId, o.OrderId, o.OrderDate };

The resulting SQL query seems quite good (removed extra parenthesis to simplify):


SELECT
    `LPA_L1`.`EmployeeID` AS `EmployeeId`,
    `LPA_L2`.`OrderID` AS `OrderId`,
    `LPA_L2`.`OrderDate`
FROM
    `employees` `LPA_L1`
LEFT JOIN `orders` `LPA_L2`
    ON `LPA_L1`.`EmployeeID` = `LPA_L2`.`EmployeeID`
WHERE
    `LPA_L2`.`OrderID` = (
        SELECT `LPLA_6`.`OrderID` AS `OrderId`
        FROM `orders` `LPLA_6`
        WHERE `LPLA_6`.`EmployeeID` = `LPA_L1`.`EmployeeID`
        ORDER BY `LPLA_6`.`OrderDate` DESC LIMIT 1
    ) OR (
        `LPA_L2`.`OrderID` IS NULL)

Thanks a lot for your great support. Hugo

hcaldeira
User
Posts: 16
Joined: 24-Mar-2009
# Posted on: 28-May-2011 18:16:01   

@Otis


SELECT
 `LPA_L1`.`EmployeeID` AS `EmployeeId`,
 `LPA_L2`.`OrderID` AS `OrderId`,
 `LPA_L2`.`OrderDate`
FROM `employees` `LPA_L1`
LEFT JOIN `orders` `LPA_L2` ON  `LPA_L2`.`OrderID` IS NULL)