从 LINQ 转换时,Linqpad returns 非常详细 SQL 查询

Linqpad returns very elaborate SQL query when converting from LINQ

我使用 LinqPad 向 return 用户编写了 LINQ 查询,这些用户应该检索问卷邀请。查询运行良好并且 returns 是正确的结果。

但是我需要 SQL 形式的查询。当我单击 LinqPad 中的 SQL 按钮时,它 return 是 SQL 表单,但每个记录都有单独的 select 语句。给我留下一个 SQL 2000 行的查询。

这是我的 LINQ 查询

var result2 = AI_Conversations
.Where(f => f.End_DateTime.Value.Date == DateTime.Now.AddDays(-1).Date).GroupBy(f => f.Email)
.Where(f => f.GroupBy(z => z.Chatbot_Name).Count() == 1)
.ToList().Select(f =>
new
{
    Name = f.LastOrDefault().Disp_Name,
    f.LastOrDefault().Email,
    Reference = f.LastOrDefault().Report_ConvNumber
});

result2.Dump();

在SQLreturn以下

-- Region Parameters
DECLARE @p0 DateTime = '2017-06-07 00:00:00.000'
DECLARE @p1 Int = 1
-- EndRegion
SELECT [t1].[Email] AS [Key]
FROM (
    SELECT [t0].[Email]
    FROM [AI_Conversations] AS [t0]
    WHERE CONVERT(DATE, [t0].[End_DateTime]) = @p0
    GROUP BY [t0].[Email]
    ) AS [t1]
WHERE ((
    SELECT COUNT(*)
    FROM (
        SELECT NULL AS [EMPTY]
        FROM [AI_Conversations] AS [t2]
        WHERE ((([t1].[Email] IS NULL) AND ([t2].[Email] IS NULL)) OR (([t1].[Email] IS NOT NULL) AND ([t2].[Email] IS NOT NULL) AND ([t1].[Email] = [t2].[Email]))) AND (CONVERT(DATE, [t2].[End_DateTime]) = @p0)
        GROUP BY [t2].[Chatbot_Name]
        ) AS [t3]
    )) = @p1
GO

在上面的语句之后,另一个 select 语句被附加到每条由 linq 查询 return 的记录。 (>200 次)

-- Region Parameters
DECLARE @p0 DateTime = '2017-06-07 00:00:00.000'
DECLARE @x1 VarChar(1000) = '(CENSORED)'
-- EndRegion
SELECT [t0].[rownames] AS [Rownames], [t0].[Report_ConvNumber], [t0].[Email], [t0].[AD_Num], [t0].[Disp_Name], [t0].[Start_DateTime], [t0].[End_DateTime], [t0].[NumOfMessages], [t0].[Duration], [t0].[Chatbot_Name], [t0].[feedback_score] AS [Feedback_score]
FROM [AI_Conversations] AS [t0]
WHERE (((@x1 IS NULL) AND ([t0].[Email] IS NULL)) OR ((@x1 IS NOT NULL) AND ([t0].[Email] IS NOT NULL) AND (@x1 = [t0].[Email]))) AND (CONVERT(DATE, [t0].[End_DateTime]) = @p0)
GO

我希望 SQL 查询 return 看起来类似于此

-- Region Parameters
DECLARE @p0 DateTime = DATEADD(dd, -1, cast(Getdate() as date))
DECLARE @p1 Int = 1
-- EndRegion
SELECT [t1].[Email],
       [t1].[Disp_Name] AS Name,
       [t1].[Report_ConvNumber] AS Reference
FROM (
    SELECT [t0].[Email],
           [t0].[Disp_Name],
           [t0].[Report_ConvNumber]
    FROM [AI_Conversations] AS [t0]
    WHERE CONVERT(DATE, [t0].[Start_DateTime]) = @p0
    GROUP BY [t0].[Email],
             [t0].[Disp_Name],
             [t0].[Report_ConvNumber]
    ) AS [t1]
WHERE ((
    SELECT COUNT(*)
    FROM (
        SELECT NULL AS [EMPTY]
        FROM [AI_Conversations] AS [t2]
        WHERE ((([t1].[Email] IS NULL) AND ([t2].[Email] IS NULL)) OR (([t1].[Email] IS NOT NULL) AND ([t2].[Email] IS NOT NULL) AND ([t1].[Email] = [t2].[Email]))) AND (CONVERT(DATE, [t2].[Start_DateTime]) = @p0)
        GROUP BY [t2].[Chatbot_Name]
        ) AS [t3]
    )) = @p1
GO

有谁能告诉我为什么 LinqPad return 进行如此冗长的 SQL 查询? 如何将 LINQ 查询调整为 return a 'simple' SQL 查询,就像我提供的期望一样?

如果重要的话,这是一个使用 Linqpad 5 的 MSSQL 2014 服务器

编辑:

按照 Sgtmoore 的建议删除 .ToList() 后,我得到了以下 SQL 输出,这或多或少符合我的预期。

    -- Region Parameters
DECLARE @p0 DateTime = '2017-05-04 00:00:00.000'
DECLARE @p1 Int = 1
-- EndRegion
SELECT (
    SELECT [t5].[AD_Num]
    FROM (
        SELECT TOP (1) [t4].[AD_Num]
        FROM [AI_Conversations] AS [t4]
        WHERE ((([t1].[Email] IS NULL) AND ([t4].[Email] IS NULL)) OR (([t1].[Email] IS NOT NULL) AND ([t4].[Email] IS NOT NULL) AND ([t1].[Email] = [t4].[Email]))) AND (CONVERT(DATE, [t4].[End_DateTime]) = @p0)
        ) AS [t5]
    ) AS [Name], (
    SELECT [t7].[Email]
    FROM (
        SELECT TOP (1) [t6].[Email]
        FROM [AI_Conversations] AS [t6]
        WHERE ((([t1].[Email] IS NULL) AND ([t6].[Email] IS NULL)) OR (([t1].[Email] IS NOT NULL) AND ([t6].[Email] IS NOT NULL) AND ([t1].[Email] = [t6].[Email]))) AND (CONVERT(DATE, [t6].[End_DateTime]) = @p0)
        ) AS [t7]
    ) AS [Email], (
    SELECT [t9].[Report_ConvNumber]
    FROM (
        SELECT TOP (1) [t8].[Report_ConvNumber]
        FROM [AI_Conversations] AS [t8]
        WHERE ((([t1].[Email] IS NULL) AND ([t8].[Email] IS NULL)) OR (([t1].[Email] IS NOT NULL) AND ([t8].[Email] IS NOT NULL) AND ([t1].[Email] = [t8].[Email]))) AND (CONVERT(DATE, [t8].[End_DateTime]) = @p0)
        ) AS [t9]
    ) AS [Reference]
FROM (
    SELECT [t0].[Email]
    FROM [AI_Conversations] AS [t0]
    WHERE CONVERT(DATE, [t0].[End_DateTime]) = @p0
    GROUP BY [t0].[Email]
    ) AS [t1]
WHERE ((
    SELECT COUNT(*)
    FROM (
        SELECT NULL AS [EMPTY]
        FROM [AI_Conversations] AS [t2]
        WHERE ((([t1].[Email] IS NULL) AND ([t2].[Email] IS NULL)) OR (([t1].[Email] IS NOT NULL) AND ([t2].[Email] IS NOT NULL) AND ([t1].[Email] = [t2].[Email]))) AND (CONVERT(DATE, [t2].[End_DateTime]) = @p0)
        GROUP BY [t2].[Chatbot_Name]
        ) AS [t3]
    )) = @p1

我认为主要问题是中间的 .ToList() 是查询。但是,如果您删除它,查询将失败,因为 Linq2Sql 不支持 LastOrDefault。

所以我认为您需要使用 .FirstOrDefault() 并在必要时反转排序顺序。

这会生成更简单的 TSQL,但仍然与您的 预期 输出完全不同。由此看来,您似乎想按电子邮件、参考资料和 Report_ConvNumber 进行分组,例如

var result2 = AI_Conversations
  .Where(f => f.End_DateTime.Value.Date == DateTime.Now.AddDays(-1).Date)
  .GroupBy(f => new {f.Email, f.Reference, f.Report_ConvNumber)
  .Where(f => f.GroupBy(z => z.Chatbot_Name).Count() == 1)
  .Select(f => new
     {
     Name = f.Key.Disp_Name,
     f.Key.Email,
     Reference = f.KeyReport_ConvNumber
   });

 result2.Dump();