c# - Linq 2 SQL查询优化

标签 c# linq linq-to-sql

我在使用 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/

相关文章:

c# - LINQ:返回列表中的非重复项

c# - 使用 LINQ 从 XML 获取最大属性值

c# - OData 查询中的 LIKE

c# - 通过对象变量将类方法的使用转换为 C# 代码

c# - 我想要以 (start,end) 为键的数据结构,然后能够在整个数据结构中搜索整数并获得相应的值

c# - 用于比较两个枚举值的 Linq 表达式

c# - XML Writer 将结果存储到字符串

c# - LINQ to SQL,检查与连接字符串的连接是否有效

asp.net-mvc-3 - 如何在 LINQ to SQL 中制作此 SQL?

c# - 继承窗体时找不到类型为 ""的构造函数