从LINQ

时间:2017-06-08 07:45:13

标签: sql sql-server linq-to-entities linqpad

我使用LinqPad编写了LINQ查询,以返回应该检索调查问卷邀请的用户。查询运行正常并返回正确的结果。

但是我需要以SQL形式提供此查询。当我单击LinqPad中的SQL按钮时,它返回SQL表单,但每个单独的记录都有一个单独的select语句。请允许我使用2000行的SQL查询。

这是我的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();

在SQL中返回以下内容

-- 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

在上面的语句之后,为linq查询返回的每条记录附加了另一个select语句。 (> 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查询看起来与此类似

-- 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会返回这么详细的SQL查询吗? 如何调整LINQ查询以返回简单的' 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

1 个答案:

答案 0 :(得分:2)

我认为主要问题是中间的.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();