将SQL子查询转换为In到Linq Lambda

如何将以下SQL语句转换为Lambda表达式或Linq查询?

以下查询获取每个问题的单个最新答案。 或者用另一种方式来表达,用最新的答案得到每个问题。

这也将由Entity Framework执行。

SELECT Answers.* FROM Answers Where AnswerID IN ( SELECT Max(AnswerID) AnswerID FROM Answers GROUP BY QuestionID ) 

这是使用内部联接查看上一个查询的另一种方法

 SELECT answers.* FROM answers INNER JOIN ( SELECT Max(answerID) answerID --, QuestionSiteID FROM answers GROUP BY QuestionID ) t ON answers.answerID = t.answerID 

我已经读过LINQ Contains方法对于访问SQL的查询是次优的。
LINQ to Sql和.Contains()陷阱。

我想你可以用以下方法做到这一点:

  var subQuery = from a in answers group a by a.QuestionID into grouping select new { QuestionID = grouping.Key, MaxAnswerID = grouping.Max(x => x.AnswerID) }; var query = from a in answers from s in subQuery where a.AnswerID == s.MaxAnswerID select a; 

这会在生成的SQL中生成CROSS JOIN


此外,您可以在查询的第二部分中使用join

  var query = from a in answers join s in subQuery on a.AnswerID equals s.MaxAnswerID select a; 

这导致SQL中的INNER JOIN


关于附带案例的注意事项 – 上面的答案做出了合理的假设,即AnswerIDAnswers的主键 – 如果碰巧有一个键设置的表设计(AnswerID,QuestionID),那么你需要通过AnswerID和QuestionID加入喜欢:

  var subQuery = from a in answers group a by a.QuestionID into grouping select new { QuestionID = grouping.Key, MaxAnswerID = grouping.Max(x => x.AnswerID) }; var query = from a in answers from s in subQuery where a.AnswerID == s.MaxAnswerID && a.QuestionID == s.QuestionID select a; 

有关此备用表设计的更多讨论,请参阅注释跟踪…

您可以使用let语句为每个QuestionID组选择第一个答案:

 from answer in Answers group answer by answer.QuestionID into question let firstAnswer = question.OrderByDescending(q => q.AnswerID).First() select firstAnswer 

编辑:Linq2Sql将上述查询转换为N + 1数据库调用。 此查询只转换为一个SQL查询:

 from a in Answers group a by a.QuestionID into grouping join a2 in Answers on new {AnswerID = grouping.Max(x => x.AnswerID), QuestionID = grouping.Key} equals new {a2.AnswerID, a2.QuestionID} select a2 

让我想知道Linq2Sql应该以什么方式比SQL更简单。

尝试使用此查询:

 var query = from c in context.Childs group c by c.ParentEntityId into pc select pc.OrderByDescending(pcc => pcc.Id).Take(1); 

我刚刚在profiler中检查了查询,它产生了单个SQL查询(丑陋的查询):

 SELECT [Project3].[ParentEntityId] AS [ParentEntityId], [Project3].[C1] AS [C1], [Project3].[Id] AS [Id], [Project3].[Name] AS [Name], [Project3].[ParentEntityId1] AS [ParentEntityId1] FROM ( SELECT [Distinct1].[ParentEntityId] AS [ParentEntityId], [Limit1].[Id] AS [Id], [Limit1].[Name] AS [Name], [Limit1].[ParentEntityId] AS [ParentEntityId1], CASE WHEN ([Limit1].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1] FROM (SELECT DISTINCT [Extent1].[ParentEntityId] AS [ParentEntityId] FROM [dbo].[ChildEntities] AS [Extent1] ) AS [Distinct1] OUTER APPLY (SELECT TOP (1) [Project2].[Id] AS [Id], [Project2].[Name] AS [Name], [Project2].[ParentEntityId] AS [ParentEntityId] FROM ( SELECT [Extent2].[Id] AS [Id], [Extent2].[Name] AS [Name], [Extent2].[ParentEntityId] AS [ParentEntityId] FROM [dbo].[ChildEntities] AS [Extent2] WHERE ([Distinct1].[ParentEntityId] = [Extent2].[ParentEntityId]) OR (([Distinct1].[ParentEntityId] IS NULL) AND ([Extent2].[ParentEntityId] IS NULL)) ) AS [Project2] ORDER BY [Project2].[Id] DESC ) AS [Limit1] ) AS [Project3] ORDER BY [Project3].[ParentEntityId] ASC, [Project3].[C1] ASC