【问题标题】:Unusual Joins SQL异常连接 SQL
【发布时间】:2016-03-08 20:48:09
【问题描述】:

我不得不将前雇员编写的代码转换为在新数据库中工作。在这样做的过程中,我遇到了一些我从未见过的连接,并且不完全理解它们是如何工作的,或者是否需要以这种方式完成它们。

连接看起来像这样:

From Table A
     Join(Table B
          Join Table C
               on B.Field1 = C.Field1)
          On A.Field1 = B.Field1

此代码的功能是否与以下代码不同:

From Table A
     Join Table B
          On A.Field1 = B.Field1
     Join Table C
          On B.Field1 = C.Field1

如果有差异,请说明第一组代码的用途。

所有这些都在 SQL Server 2012 中完成。提前感谢您提供的任何帮助。

【问题讨论】:

  • 这并不罕见。您正在子查询中创建数据子集,允许您对子集与整个集合执行操作,如分组,如示例二所示。
  • 我总是发现 from 子句中的括号非常令人困惑(除了描述派生表)。在我的一生中,我从来没有用括号写过联接(而且我写过成千上万的查询)。括号只是为了混淆。话虽如此,声明的结果是相同的。虽然它可能会强制连接顺序,但优化器无论如何都会做它认为合适的事情。在带有 LEFT/RIGHT/FULL 连接的语句中,需要进行一些调查。
  • @SteveMangiameli 我不确定我是否会跟随您对子集与整个集合进行分组。由于 B 中的同一字段等于 C 中的字段,因此 A 不会对一个字段进行分组以相同的方式影响另一个字段。我唯一一次看到子集上的分组是在执行完整的选择语句作为子查询时。虽然我对这一切还是很陌生。在旁注中,人们有什么理由在联接中编写完整的 Select 语句,而不是仅仅创建一个临时表并加入该表。在我看来,这样阅读要容易得多。
  • 几个原因,都与资源和性能有关。我会在答案中举一个例子。
  • "[...]full select statement as the subquery" >>简称为派生表。

标签: join sql-server-2012


【解决方案1】:

我可以创建一个临时表,然后加入它。但是,如果我可以即时执行此操作,为什么要在额外的存储和索引上使用周期\RAM?

我今天在 SSRS 中遇到了这种情况 - 一个用户想要查看所有通过 AD 组授予访问权限的个人。用户使用游标和一些临时表让用户退出 AD,然后将用户加入与 AD 组关联的每个 SSRS 对象(文件夹、报表、链接报表)。我用 Cross Apply 和一个子查询简化了整个事情。

GroupMembers 表

  • 组名
  • 用户 ID
  • 用户名
  • 帐户类型
  • AccountTypeDesc

SSRSOjbects_Permissions 表

  • 路径
  • 路径类型
  • 角色名称
  • 角色描述
  • 名称(AD 组名称)

查询需要返回与每个报告关联的 AD 组中的每个人。基本上是用户在数据子集内报告的笛卡尔积。最简单的方法如下所示:

select 
    G.GroupName, G.UserID, G.Name, G.AccountType, G.AccountTypeDesc,
    [Path], PathType, RoleName, RoleDesc
from 
    GroupMembers G
cross apply 
    (select 
         [Path], PathType, RoleName, RoleDesc 
     from 
         SSRSOjbects_Permissions  
     where 
         Name = G.GroupName) S;

你可以通过一个临时表和一些外部连接来实现这一点,但是为什么要浪费系统资源呢?

【讨论】:

  • 史蒂夫这太棒了,这真的帮助我理解了完整选择与临时表的意义。但这里更重要的部分是自从我开始使用 SQL 以来,我一直想知道 Cross Apply 是否有用过。除了制作一个假数据库来摆弄之外,我从来没有见过我迄今为止所做的事情。所以感谢你在现实生活中使用它,即使你不知道我很好奇。 :)
【解决方案2】:

我看到了这种连接——它是用于处理多表连接的 MS Access 样式。在 MS Access 中,您需要将每个后续 join 语句嵌套到其级别括号中。所以,例如这个 T-SQL 连接:

SELECT a.columna, b.columnb, c.columnc
FROM tablea AS a 
LEFT JOIN tableb AS b ON a.id = b.id 
LEFT JOIN tablec AS c ON a.id = c.id

你应该转换成这个:

SELECT a.columna, b.columnb, c.columnc
FROM ((tablea AS a) LEFT JOIN tableb AS b ON a.id = b.id) LEFT JOIN tablec AS c ON a.id = c.id

所以,是的,我相信你的假设是正确的

【讨论】:

  • 所以你说这很可能是因为前雇员有 MS Access 背景。有道理。
  • 听起来很有可能。就我而言,情况恰恰相反。我必须编写具有 T-SQL 背景的 MS Access 查询,我对这些嵌套连接感到非常惊讶:)
  • Here 是规则(在底部)
猜你喜欢
  • 2011-07-28
  • 1970-01-01
  • 2021-09-28
  • 2016-03-10
  • 1970-01-01
  • 2012-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多