【问题标题】:LINQ2SQL - More Questions on when a Cross join with where clause is emitted instead of Inner JoinLINQ2SQL - 关于何时发出带有 where 子句的交叉连接而不是内部连接的更多问题
【发布时间】:2011-03-17 05:43:14
【问题描述】:

这是一个由两部分组成的问题,用于教育目的,而不是试图找到问题的解决方案。

我已经看过这个并意识到它与我的问题非常相似

LINQ2SQL - Cross join emitted when I want inner join

但我希望 LINQ 和 SQL 专家能提供更多关于为什么在 LINQ2SQL 中创建交叉联接而不是内部联接的信息。此外,有人可以解释 SQL Server 如何决定执行计划(或链接到更多信息),因为这两个查询都会生成相同的计划?据我了解,这意味着查询的性能是相同的。

我创建了一个小示例,在我的数据库上运行两个 LINQ 表达式,生成这两个不同的 SQL 查询。

对于那些不想打扰的人,这是我的示例数据库图: http://dl.dropbox.com/u/13256/Screen%20shot%202011-03-16%20at%2011.41.56%20AM.png

以下是两个查询: 使用 Where 子句交叉连接

var q = from item in context.Items
join i_mem in context.Memberships on new { item_id = item.ID, user_id = 
current_user_id.Value } equals new { item_id = i_mem.RelatedItemID, user_id = 
i_mem.RelatedUserID } into sq_i_m
from im in sq_i_m.DefaultIfEmpty()
join i_cat in context.Categories on item.RelatedCategoryID equals i_cat.ID 
into sq_i_cat
from proj in sq_i_cat
select item;

内连接

from item in context.Items
join i_mem in context.Memberships on
new { item_id = item.ID, user_id = current_user_id.Value }
equals
new { item_id = i_mem.RelatedItemID, user_id = i_mem.RelatedUserID }
into sq_i_m
from im in sq_i_m.DefaultIfEmpty()
join i_cat in context.Categories on item.RelatedCategoryID equals i_cat.ID
select item

如果您想亲眼看看,here 是测试程序。

感谢大家的帮助。

穆斯塔法

【问题讨论】:

  • 您确实知道,如果您在 .dbml 文件中设置了关系,则无需在代码中进行文字连接即可访问其他表。
  • @Nick - 例如:从 i in context.Items where i.RelatedMembership.CreatedOn

标签: c# .net sql-server-2005 linq-to-sql


【解决方案1】:

它们是同一个东西,所以 LINQ2SQL 发出哪个并不重要。

inner join 在逻辑上等同于带有where 子句过滤器的交叉连接,该过滤器等效于inner join 子句的on

这就是 Sql Server 生成相同查询计划的原因。

要清楚,内连接:

Select f1 
From T1 inner join T2 on T1.k = T2.k
where T1.f2 like 'X%'

和cross join一样:

Select f1 
From T1 cross join T2 
where T1.k = T2.k
and T1.f2 like 'X%'

与旧式 SQL 相同:

Select f1 
From T1, T2 
where T1.k = T2.k
and T1.f2 like 'X%'

【讨论】:

  • 所以,如果我是直接用 TSQL 写出来的,那纯粹是我选择我喜欢哪种语法决定了我使用哪种风格?正如我之前提到的,“似乎”对连接进行过滤会比进行连接和 where 子句创建更有效的执行计划。只谈 SQL - 如果我使用的是 SQL Server 以外的其他 RDMS,那么上述所有样式之间的执行计划是否一定相同?
【解决方案2】:

假设您有一个名为 MyDataContext 的数据上下文。

using(MyDataContext db = new MyDataContext())
{
  var q = db.Items.Where(x=> x.Categories.Name == "myCategory").Select(x=> x);
}

这是一个非常简单的示例,但您不需要以TSQL 语法写出连接或子查询。 (我讨厌写 TSQL)。

【讨论】:

  • 可能只是因为我过去写了很多 TSQL 并且仍然经常这样“思考”,但我不介意语法。感谢您的示例,我显然也看到了这种语法,并且也使用它。不过,再次想知道更多关于 LINQ 是如何生成 SQL 和 1. 它是否重要,因为 sql server 上的执行计划是相同的,或者 2. sql server 怎么这么聪明?
  • @Mustafakidd,一位微软程序员编写了所有代码来翻译它,这与 LINQ 是否“智能”无关。至于使用查询表达式语法或点表示法/lambda 语法,请注意某些操作仅适用于 lambda,例如 Single()、First()、Count()。但是,如果您确实想使用连接,那么查询语法更容易编写/阅读。
  • 是“开玩笑”,但也指的是 SQL 服务器知道如何创建相同的执行计划,无论在实际 TSQL 查询中使用的是内部联接还是交叉联接。 Instinct 说内部连接比带有 where 子句的交叉连接更有效,但显然这不是真的。
猜你喜欢
  • 2013-12-13
  • 1970-01-01
  • 2011-09-05
  • 2012-09-04
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 2011-01-01
  • 1970-01-01
相关资源
最近更新 更多