简体   繁体   English

如何在实体框架中编写此SQL查询?

[英]How to write this SQL query in Entity Framework?

I have this query that I want translated pretty much 1:1 from Entity Framework to SQL: 我有这个查询,我想将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

This SQL query should sort based on the number occurrence of the same ItemId (for that group). 此SQL查询应基于相同ItemId (针对该组)的出现次数进行排序。

I have this now: 我现在有这个:

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()};

But this generates the following SQL code: 但这会生成以下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

This also works but is a factor 2 slower than the SQL I created. 这也可以,但是比我创建的SQL慢2倍。

I've been fiddling around with the linq code for a while but I haven't managed to create something similar to my query. 我已经摆弄了linq代码一段时间了,但是我没有设法创建类似于查询的内容。

Execution plan (only the last two items, the first two are identical): 执行计划(仅最后两项,前两项相同):

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)

The query that Entity Framework generates and your hand crafted query are semantically the same and will give the same plan. Entity Framework生成的查询和您的手工查询在语义上是相同的,并将提供相同的计划。

The derived table definition is inlined during query optimisation so the only difference might be some extremely minor additional overhead during parsing and compilation. 在查询优化过程中内联了派生的表定义,因此唯一的区别可能是在解析和编译过程中有极少量的额外开销。

The snippets of SHOWPLAN_TEXT you have posted are the same plan. 您发布的SHOWPLAN_TEXT的代码段是同一计划。 The only difference is aliases. 唯一的区别是别名。 It looks as though your table definition is something like. 看起来您的表定义有点像。

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

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

And you are getting a plan like this 而且您正在获得这样的计划

计划

To all intents and purposes the plans are the same. 在所有意图和目的上,计划都是相同的。 Your performance testing methodology is probably flawed. 您的性能测试方法可能存在缺陷。 Maybe your first query brought pages into cache that then benefited the second query for example. 也许您的第一个查询将页面带入缓存,然后使第二个查询受益。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM