c# - 如何在 Entity Framework 中编写此 SQL 查询?

标签 c# sql-server sql-server-2008 entity-framework

我有一个查询,我想将其从 Entity Framework 1:1 转换为 SQL:

SELECT GroupId, ItemId, count(*) as total
  FROM [TESTDB].[dbo].[TestTable]
  WHERE GroupId = '64025'
  GROUP BY GroupId, ItemId
  ORDER BY GroupId, total DESC

此 SQL 查询应根据相同 ItemId(针对该组)的出现次数进行排序。

我现在有这个:

from x in dataContext.TestTable.AsNoTracking()
where x.GroupId = 64025
group x by new {x.GroupId, x.ItemId}
into g
orderby g.Key.GroupId, g.Count() descending 
select new {g.Key.GroupId, g.Key.ItemId, Count = g.Count()};

但这会生成以下 SQL 代码:

SELECT 
  [GroupBy1].[K1] AS [GroupId], 
  [GroupBy1].[K2] AS [ItemId], 
  [GroupBy1].[A2] AS [C1]
FROM ( SELECT 
         [Extent1].[GroupId] AS [K1], 
         [Extent1].[ItemId] AS [K2], 
         COUNT(1) AS [A1], 
         COUNT(1) AS [A2]
       FROM [dbo].[TestTable] AS [Extent1]
       WHERE 64025 = [Extent1].[GroupId]
       GROUP BY [Extent1].[GroupId], [Extent1].[ItemId]
     )  AS [GroupBy1]
ORDER BY [GroupBy1].[K1] ASC, [GroupBy1].[A1] DESC

这也有效,但比我创建的 SQL 慢 2 倍。

我已经摆弄 linq 代码有一段时间了,但我还没有设法创建与我的查询类似的东西。

执行计划(只有最后两项,前两项相同):

FIRST:   |--Stream Aggregate(GROUP BY:([Extent1].[ItemId]) DEFINE:([Expr1006]=Count(*), [Extent1].[GroupId]=ANY([TESTDB].[dbo].[TestTable].[GroupId] as [Extent1].[GroupId])))
           |--Index Seek(OBJECT:([TESTDB].[dbo].[TestTable].[IX_Group]), SEEK:([TESTDB].[dbo].[TestTable].[GroupId]=(64034)) ORDERED FORWARD)

SECOND:  |--Stream Aggregate(GROUP BY:([TESTDB].[dbo].[TestTable].[ItemId]) DEFINE:([Expr1007]=Count(*), [TESTDB].[dbo].[TestTable].[GroupId]=ANY([TESTDB].[dbo].[TestTable].[GroupId])))
           |--Index Seek(OBJECT:([TESTDB].[dbo].[TestTable].[IX_Group] AS [Extent1]), SEEK:([Extent1].[GroupId]=(64034)) ORDERED FORWARD)

最佳答案

Entity Framework 生成的查询和您手工制作的查询在语义上是相同的,并且会给出相同的计划。

派生表定义在查询优化期间内联,因此唯一的区别可能是解析和编译期间的一些极小的额外开销。

您发布的 SHOWPLAN_TEXT 片段是相同的计划。唯一的区别是别名。看起来你的表定义是这样的。

CREATE TABLE [dbo].[TestTable] 
(
[GroupId] INT,
[ItemId] INT
)

CREATE NONCLUSTERED INDEX IX_Group ON  [dbo].[TestTable] ([GroupId], [ItemId]) 

你会得到这样的计划

Plan

就所有意图和目的而言,计划都是相同的。您的性能测试方法可能有缺陷。例如,也许您的第一个查询将页面放入缓存,然后使第二个查询受益。

关于c# - 如何在 Entity Framework 中编写此 SQL 查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14181334/

相关文章:

c# - Azure 表存储,表。执行返回无效实体

c# - LINQ to Entities 无法识别嵌套选择中的“System.Linq.IQueryable”方法

c# - 在 TFS 或共享文件夹中存储内容图像以便在多个网站中使用的正确方法是什么?

c# - 自 SQL 2008 升级以来,SqlDataReader.HasRows 返回 false

asp.net - 对于 CRUD 来说,以下哪一个是更好的实践? Simple.Data 还是 Dapper?

c# - 登录失败 : the user has not been granted the requested logon type at this computer

SQL 计算平均值

sql - 通过 Linux (Ubuntu 16) 安装和配置 SQL Server 2008 R2 全文搜索

sql-server - 如何记录存储过程调用?

sql - 在 SQL 中查找 "next but one newest"日期的最佳方法是什么?