5

根据所有示例,SQL 转换为 HAVING 子句的 LINQ,如下例所示:

SELECT NAME
FROM TABLES
GROUP BY NAME
HAVING COUNT(*) > 1

是:(vb.net)

from t in tables 
group t by t.NAME into g = Group 
where g.count > 1 
select g

但是上面的 LINQ 语句被翻译成下面的 SQL:


SELECT [t1].[NAME] AS [Key]
FROM (
    SELECT COUNT(*) AS [value], [t0].[NAME]
    FROM [tables] AS [t0]
    WHERE [t0].[NAME] <> @p0
    GROUP BY [t0].[NAME]
    ) AS [t1]
WHERE [t1].[value] > @p1

我从来没有成功地从 LINQ 生成 HAVING 子句。假设 HAVING 和子查询 group by with WHERE 在结果上是等价的,但是在性能上有区别吗?如何让我的原始 SQL 查询至少类似于 LINQ 生成的底层查询?

4

1 回答 1

4

您可以通过查看执行计划来演示 SQL Server 是否以相同的方式执行有问题的两个查询。采取以下测试代码(我使用的是 SQL Server 2008):

CREATE TABLE #TABLES ([ID] INT IDENTITY, [Name] VARCHAR(30))
INSERT INTO #TABLES VALUES('A')
INSERT INTO #TABLES VALUES('A')
INSERT INTO #TABLES VALUES('B')
INSERT INTO #TABLES VALUES('C')
INSERT INTO #TABLES VALUES('D')

SELECT NAME
FROM #TABLES
WHERE [Name] <> 'D'
GROUP BY NAME
HAVING COUNT(*) > 1

SELECT [t1].[NAME]
FROM (
    SELECT COUNT(*) AS [value], [t0].[NAME]
    FROM [#TABLES] AS [t0]
    WHERE [t0].[NAME] <> 'D'
    GROUP BY [t0].[NAME]
    ) AS [t1]
WHERE [t1].[value] > 1

DROP TABLE #TABLES

在“查询”菜单下选择“包括实际执行计划”从 SQL 查询分析器执行这些查询将产生以下输出:

执行计划

在这种情况下,由于生成的查询计划完全相同,显然您的 SQL 和从您的 LINQ 语句生成的 SQL 之间应该没有性能差异。

附带说明一下,不幸的是,我找不到任何文档说明为什么 LinqToSql 不使用 HAVING,或者使用 HAVING 与使用子选择是否会以一种或另一种方式获得性能提升。如果我不得不猜测,我会说 SQL Server 中的查询优化器在执行这些语句之前在内部将它们转换为相同的查询,这就是为什么两个语句的执行计划相同的原因。无论我之前的陈述是否属实,如果您有任何疑问,请查看您的 SQL 版本与 LinqToSql 版本的执行计划。如果它们相同,那么您无需担心性能方面的问题。如果您的 SQL 版本效率更高,那么您总是可以编写一个存储过程并使用 LinqToSql 调用该存储过程。

于 2011-11-23T15:52:24.777 回答