我在使用 linq to sql 查询时遇到了一个真正的问题,这可能是因为我的 skilz 有点欠缺,但如果有人能看看我如何优化查询作为 SQL,我将不胜感激正在生成的是可怕的
查询的目的是尝试获取加入销售明细表的位置的库存概览,以根据部门 ID(即一个部门中的所有产品)因此 Max() 和 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;
然后由此生成的 SQL 是... 这似乎是在使用相同的数据集分别查询 MAX 和 SUM,而实际上应该一起完成查询,这使得查询变得非常复杂,而且实际查询需要很长时间
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))
我实际上试图转换为链接的查询是这个
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
所以我认为需要进行一些真正的优化,而且我似乎真的无法弄清楚我在 linq 查询中做错了什么。
干杯 乔。
最佳答案
是的,当您的查询变得复杂时,linq to sql 和其他类似的生成器往往会失败。
您的选择是绕过 linq 手动执行查询,或者在数据库上创建一个函数并执行该形式的 linq。
关于c# - Linq 2 SQL查询优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27442526/