I am having a real problem with a linq to sql query, and it is probable because my skilz are a bit lacking, but i would appreciate it if anyone can have a look and see how i can optimize the query as the SQL that is being generated is horrific
What the query is doing, is trying to get a stock overview for the locations joining on the sales details table to find out when the last sale was made and the quantity of stock at that location based on a department id (that being all products in a department) hence the Max() and Sum()
var query1 = (
from sl in slRepo
where sl.Product.bsDepartmentId < 90 && sl.Product.SubDepartment.Department.Id == departmentId
group sl by sl.Location into gbsl
select new
{
ProductId = gbsl.FirstOrDefault().Product.Id,
LocationId = gbsl.FirstOrDefault().Location.Id,
Location = gbsl.FirstOrDefault().Location.Name,
Quantity = gbsl.Sum(x => x.CurrentStock),
LastInvoice = gbsl.Max(x => x.LastInvoice)
});
var query2 = (
from sd in sdRepo
where sd.Product.SubDepartment.Department.Id == departmentId
group sd by sd.Location.Id into g
select new
{
LocationId = g.FirstOrDefault().Location.Id,
LastSale = g.Max(x => x.TransactionDate)
});
var query3 = (
from q1 in query1
join q2 in query2 on q1.LocationId equals q2.LocationId into temp
from j in temp.DefaultIfEmpty()
select new XStockOverviewDto
{
Location = q1.Location,
Quantity = q1.Quantity,
LastInvoice = q1.LastInvoice,
LastSale = j.LastSale
});
return query3;
And then the SQL being generated from this is... which seems to being using the same datasets to query the MAX and the SUM separately when it should be done together making the query far to complicated and it takes a hell of a long time to actually query
SELECT
1 AS [C1],
[Project10].[Name] AS [Name],
[Project10].[C2] AS [C2],
[Project10].[C3] AS [C3],
CAST( [Project16].[C2] AS datetime2) AS [C4]
FROM (SELECT
[Project9].[Name] AS [Name],
[Project9].[C1] AS [C1],
[Project9].[C2] AS [C2],
(SELECT
MAX([Filter9].[LastInvoice]) AS [A1]
FROM ( SELECT [Extent18].[LastInvoice] AS [LastInvoice], [Extent20].[Department_Id] AS [Department_Id], [Extent21].[Id] AS [Id1]
FROM [dbo].[XStockLevels] AS [Extent18]
INNER JOIN [dbo].[XProducts] AS [Extent19] ON [Extent18].[Product_Id] = [Extent19].[Id]
LEFT OUTER JOIN [dbo].[XSubDepartments] AS [Extent20] ON [Extent19].[SubDepartment_Id] = [Extent20].[Id]
LEFT OUTER JOIN [dbo].[XLocations] AS [Extent21] ON [Extent18].[Location_Id] = [Extent21].[Id]
WHERE [Extent19].[bsDepartmentId] < 90
) AS [Filter9]
WHERE ([Filter9].[Department_Id] = @p__linq__0) AND (([Project9].[Id] = [Filter9].[Id1]) OR (([Project9].[Id] IS NULL) AND ([Filter9].[Id1] IS NULL)))) AS [C3]
FROM ( SELECT
[Project8].[Id] AS [Id],
[Project8].[Name] AS [Name],
[Project8].[C1] AS [C1],
(SELECT
SUM([Filter7].[CurrentStock]) AS [A1]
FROM ( SELECT [Extent14].[CurrentStock] AS [CurrentStock], [Extent16].[Department_Id] AS [Department_Id], [Extent17].[Id] AS [Id2]
FROM [dbo].[XStockLevels] AS [Extent14]
INNER JOIN [dbo].[XProducts] AS [Extent15] ON [Extent14].[Product_Id] = [Extent15].[Id]
LEFT OUTER JOIN [dbo].[XSubDepartments] AS [Extent16] ON [Extent15].[SubDepartment_Id] = [Extent16].[Id]
LEFT OUTER JOIN [dbo].[XLocations] AS [Extent17] ON [Extent14].[Location_Id] = [Extent17].[Id]
WHERE [Extent15].[bsDepartmentId] < 90
) AS [Filter7]
WHERE ([Filter7].[Department_Id] = @p__linq__0) AND (([Project8].[Id] = [Filter7].[Id2]) OR (([Project8].[Id] IS NULL) AND ([Filter7].[Id2] IS NULL)))) AS [C2]
FROM ( SELECT
[Project7].[Id] AS [Id],
[Extent13].[Name] AS [Name],
[Project7].[C1] AS [C1]
FROM (SELECT
[Project5].[Id] AS [Id],
[Project5].[C1] AS [C1],
(SELECT TOP (1)
[Filter5].[Location_Id] AS [Location_Id]
FROM ( SELECT [Extent9].[Location_Id] AS [Location_Id], [Extent11].[Department_Id] AS [Department_Id], [Extent12].[Id] AS [Id3]
FROM [dbo].[XStockLevels] AS [Extent9]
INNER JOIN [dbo].[XProducts] AS [Extent10] ON [Extent9].[Product_Id] = [Extent10].[Id]
LEFT OUTER JOIN [dbo].[XSubDepartments] AS [Extent11] ON [Extent10].[SubDepartment_Id] = [Extent11].[Id]
LEFT OUTER JOIN [dbo].[XLocations] AS [Extent12] ON [Extent9].[Location_Id] = [Extent12].[Id]
WHERE [Extent10].[bsDepartmentId] < 90
) AS [Filter5]
WHERE ([Filter5].[Department_Id] = @p__linq__0) AND (([Project5].[Id] = [Filter5].[Id3]) OR (([Project5].[Id] IS NULL) AND ([Filter5].[Id3] IS NULL)))) AS [C2]
FROM ( SELECT
[Project4].[Id] AS [Id],
[Project4].[C1] AS [C1]
FROM ( SELECT
[Project2].[Id] AS [Id],
(SELECT TOP (1)
[Filter3].[Location_Id] AS [Location_Id]
FROM ( SELECT [Extent5].[Location_Id] AS [Location_Id], [Extent7].[Department_Id] AS [Department_Id], [Extent8].[Id] AS [Id4]
FROM [dbo].[XStockLevels] AS [Extent5]
INNER JOIN [dbo].[XProducts] AS [Extent6] ON [Extent5].[Product_Id] = [Extent6].[Id]
LEFT OUTER JOIN [dbo].[XSubDepartments] AS [Extent7] ON [Extent6].[SubDepartment_Id] = [Extent7].[Id]
LEFT OUTER JOIN [dbo].[XLocations] AS [Extent8] ON [Extent5].[Location_Id] = [Extent8].[Id]
WHERE [Extent6].[bsDepartmentId] < 90
) AS [Filter3]
WHERE ([Filter3].[Department_Id] = @p__linq__0) AND (([Project2].[Id] = [Filter3].[Id4]) OR (([Project2].[Id] IS NULL) AND ([Filter3].[Id4] IS NULL)))) AS [C1]
FROM ( SELECT
[Distinct1].[Id] AS [Id]
FROM ( SELECT DISTINCT
[Filter1].[Id5] AS [Id],
[Filter1].[bsLocationId] AS [bsLocationId],
[Filter1].[Name] AS [Name],
[Filter1].[Code1] AS [Code1],
[Filter1].[Code2] AS [Code2],
[Filter1].[Code3] AS [Code3],
[Filter1].[Code4] AS [Code4],
[Filter1].[Code5] AS [Code5],
[Filter1].[Code6] AS [Code6],
[Filter1].[Code7] AS [Code7],
[Filter1].[Code8] AS [Code8],
[Filter1].[bsCompanyId] AS [bsCompanyId],
[Filter1].[Group] AS [Group]
FROM ( SELECT [Extent3].[Department_Id] AS [Department_Id], [Extent4].[Id] AS [Id5], [Extent4].[bsLocationId] AS [bsLocationId], [Extent4].[Name] AS [Name], [Extent4].[Code1] AS [Code1], [Extent4].[Code2] AS [Code2], [Extent4].[Code3] AS [Code3], [Extent4].[Code4] AS [Code4], [Extent4].[Code5] AS [Code5], [Extent4].[Code6] AS [Code6], [Extent4].[Code7] AS [Code7], [Extent4].[Code8] AS [Code8], [Extent4].[bsCompanyId] AS [bsCompanyId], [Extent4].[Group] AS [Group]
FROM [dbo].[XStockLevels] AS [Extent1]
INNER JOIN [dbo].[XProducts] AS [Extent2] ON [Extent1].[Product_Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[XSubDepartments] AS [Extent3] ON [Extent2].[SubDepartment_Id] = [Extent3].[Id]
LEFT OUTER JOIN [dbo].[XLocations] AS [Extent4] ON [Extent1].[Location_Id] = [Extent4].[Id]
WHERE [Extent2].[bsDepartmentId] < 90
) AS [Filter1]
WHERE [Filter1].[Department_Id] = @p__linq__0
) AS [Distinct1]
) AS [Project2]
) AS [Project4]
) AS [Project5] ) AS [Project7]
LEFT OUTER JOIN [dbo].[XLocations] AS [Extent13] ON [Project7].[C2] = [Extent13].[Id]
) AS [Project8]
) AS [Project9] ) AS [Project10]
LEFT OUTER JOIN (SELECT
[Project15].[C1] AS [C1],
(SELECT
MAX([Extent28].[TransactionDate]) AS [A1]
FROM [dbo].[XSalesDetails] AS [Extent28]
LEFT OUTER JOIN [dbo].[XProducts] AS [Extent29] ON [Extent28].[Product_Id] = [Extent29].[Id]
INNER JOIN [dbo].[XSubDepartments] AS [Extent30] ON [Extent29].[SubDepartment_Id] = [Extent30].[Id]
WHERE ([Extent30].[Department_Id] = @p__linq__1) AND (([Project15].[Location_Id] = [Extent28].[Location_Id]) OR (([Project15].[Location_Id] IS NULL) AND ([Extent28].[Location_Id] IS NULL)))) AS [C2]
FROM ( SELECT
[Project14].[Location_Id] AS [Location_Id],
[Project14].[C1] AS [C1]
FROM ( SELECT
[Project12].[Location_Id] AS [Location_Id],
(SELECT TOP (1)
[Extent25].[Location_Id] AS [Location_Id]
FROM [dbo].[XSalesDetails] AS [Extent25]
LEFT OUTER JOIN [dbo].[XProducts] AS [Extent26] ON [Extent25].[Product_Id] = [Extent26].[Id]
INNER JOIN [dbo].[XSubDepartments] AS [Extent27] ON [Extent26].[SubDepartment_Id] = [Extent27].[Id]
WHERE ([Extent27].[Department_Id] = @p__linq__1) AND (([Project12].[Location_Id] = [Extent25].[Location_Id]) OR (([Project12].[Location_Id] IS NULL) AND ([Extent25].[Location_Id] IS NULL)))) AS [C1]
FROM ( SELECT
@p__linq__1 AS [p__linq__1],
[Distinct2].[Location_Id] AS [Location_Id]
FROM ( SELECT DISTINCT
[Extent22].[Location_Id] AS [Location_Id]
FROM [dbo].[XSalesDetails] AS [Extent22]
LEFT OUTER JOIN [dbo].[XProducts] AS [Extent23] ON [Extent22].[Product_Id] = [Extent23].[Id]
INNER JOIN [dbo].[XSubDepartments] AS [Extent24] ON [Extent23].[SubDepartment_Id] = [Extent24].[Id]
WHERE [Extent24].[Department_Id] = @p__linq__1
) AS [Distinct2]
) AS [Project12]
) AS [Project14]
) AS [Project15] ) AS [Project16] ON ([Project10].[C1] = [Project16].[C1]) OR (([Project10].[C1] IS NULL) AND ([Project16].[C1] IS NULL))
The query that i am actually trying to convert to link is this
DECLARE @DeptId INT = 1;
SELECT Location_Id, XLocations.Name, CurrentStock, LastInvoice, LastSale
FROM
(SELECT Location_Id, SUM(CurrentStock) AS CurrentStock, MAX(LastInvoice) AS LastInvoice, MAX(LastSale) AS LastSale
FROM XStockLevels
LEFT JOIN
(SELECT XProducts.bsDepartmentId, XProducts.bsSubDepartmentId, XProducts.bsItemId, XProducts.Id, LastSale
FROM XProducts
INNER JOIN XSubDepartments ON XProducts.SubDepartment_Id = XSubDepartments.Id
LEFT JOIN (SELECT Product_Id, MAX(TransactionDate) AS LastSale FROM XSalesDetails GROUP BY Product_Id) XSD ON XSD.Product_Id = XProducts.Id
WHERE XProducts.bsDepartmentId<90 AND XSubDepartments.Department_Id = @DeptId) XP
ON XStockLevels.Product_Id = XP.Id
GROUP BY Location_Id) Z
INNER JOIN XLocations ON Z.Location_Id = XLocations.Id
So i think there is some real optimization that needs to happen, and i really cant seem to figure out what i am doing wrong in my linq query.
Cheers Joe.