SQL风格的问题:内部连接FROM子句还是WHERE子句?

SQL风格的问题:内部连接FROM子句还是WHERE子句?,sql,database,Sql,Database,如果要在一个SQL查询中连接多个表,您认为将join语句放在哪里更好:在FROM子句还是where子句中 如果要在FROM子句中执行此操作,如何设置格式以使其清晰易读?我说的是缩进,换行,空白 每种方法都有优点/缺点吗?我倾向于使用FROM子句,或者更确切地说是JOIN子句本身,像这样缩进并使用别名: SELECT t1.field1, t2.field2, t3.field3 FROM table1 t1 INNER JOIN table2 t2 ON t1.id1 = t2.id

如果要在一个SQL查询中连接多个表,您认为将join语句放在哪里更好:在FROM子句还是where子句中

如果要在FROM子句中执行此操作,如何设置格式以使其清晰易读?我说的是缩进,换行,空白

每种方法都有优点/缺点吗?

我倾向于使用FROM子句,或者更确切地说是JOIN子句本身,像这样缩进并使用别名:

SELECT t1.field1, t2.field2, t3.field3
FROM table1 t1
  INNER JOIN table2 t2
    ON t1.id1 = t2.id1
  INNER JOIN table3 t3
    ON t1.id1 = t3.id3

这将使连接条件保持在靠近进行连接的位置。我发现这样更容易理解,然后尝试通过WHERE子句来找出连接的确切方式。

我几乎总是使用ANSI 92连接,因为它清楚地表明这些条件是用于连接的

通常我是这样写的

FROM
    foo f
    INNER JOIN bar b
    ON f.id = b.id
有时候我这样写,当它琐碎的时候

FROM
    foo f
    INNER JOIN bar b  ON f.id = b.id
    INNER JOIN baz b2  ON b.id = b2.id
当它不是琐碎的时候,我会用第一种方法

e、 g

或者真的很奇怪,我不确定我是否正确地得到了paren,但是它应该是一个到table bar的左连接,但是bar需要一个到baz的内部连接

FROM 
     foo f
     LEFT JOIN (bar b
          INNER JOIN baz b2 
           ON b.id = b2.id
      )ON f.id = b.id

你应该把连接放在连接子句中,这意味着From子句。关于将过滤语句放在哪里,可能会有一个不同的问题

关于缩进,有许多样式。我的偏好是缩进相关的联接,并将Select、From、Where、Group By、Having和Order By等主要子句缩进在同一级别。此外,我将这些主要属性和On子句的第一行放在自己的行中

Select ..
From Table1
    Join Table2
        On Table2.FK = Table1.PK
           And Table2.OtherCol = '12345'
           And Table2.OtherCol2 = 9876
    Left Join (Table3
        Join Table4
            On Table4.FK = Table3.PK)
        On Table3.FK = Table2.PK
Where ...
Group By ...
Having ...
Order By ...

在进行外部连接ANSI-89或ANSI-92时,过滤位置很重要,因为在进行连接之前应用了ON子句中指定的标准。连接完成后,将应用WHERE子句中提供的外部连接表的条件。这会产生非常不同的结果集


相比之下,如果ON或WHERE子句中提供了条件,则内部联接并不重要——结果将是相同的。也就是说,我努力保持WHERE子句的干净性——与联接表相关的任何内容都将在它们各自的ON子句中。保存WHERE子句,这就是为什么ANSI-92语法更具可读性的原因。

使用FROM子句以符合ANSI-92标准

这:

不是这个:

select *
    from a, b
    where a.id = b.id
        and a.SomeColumn = 'x'

我更喜欢FROM子句,如果没有其他原因,它将过滤结果与笛卡尔乘积、外键关系和逻辑限制区分开来。例如:

SELECT * FROM Products P JOIN ProductPricing PP ON P.Id = PP.ProductId
WHERE PP.Price > 10
相对于

SELECT * FROM Products P, ProductPricing PP 
WHERE P.Id = PP.ProductID AND Price > 10

我可以看到第一个,立即知道我唯一的逻辑限制是价格,而不是在关系键上将表连接在一起的隐含机制。

我肯定总是在FROM子句中进行任何类型的连接

我缩进它们的方式如下:

SELECT fields
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.t1_id
INNER JOIN table3 t3 ON t1.id = t3.t1_id
    AND
    t2.id = t3.t2_id
事实上,我通常会更进一步,将尽可能多的约束逻辑从WHERE子句移到from子句,因为这至少在MS SQL front中加载了约束,这意味着它在查询构造中更快地减小了记录集的大小我看到了与此相矛盾的文档,但当我这样做时,我的执行计划总是更有效率

例如,如果我只想在上面的查询中选择t3.id=3的内容,可以在where子句中选择,也可以这样做:

SELECT fields
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.t1_id
INNER JOIN table3 t3 ON t1.id = t3.t1_id
    AND
    t2.id = t3.t2_id
    AND
    t3.id = 3
我个人认为以这种方式列出的查询非常可读和可维护,但这肯定是个人偏好的问题,所以YMMV


无论如何,我希望这能有所帮助。

ANSI加入。我省略了SQL中的任何可选关键字,因为它们只会给等式增加噪音。不存在左内连接,是吗?默认情况下,简单连接是内部连接,所以说“内部连接”没有什么特别的意义

然后我会尽可能多地排列东西

关键是一个大型复杂的SQL查询可能很难理解,因此为了使其更具可读性而对其施加的顺序越多越好。任何查看查询以修复、修改或调整查询的机构都需要能够立即回答一些问题:

查询涉及哪些表/视图? 每次加入的标准是什么?每个连接的基数是多少? 查询返回的列数/列数 我喜欢写我的查询,使它们看起来像这样:

select PatientID              = rpt.ipatientid ,
       EventDate              = d.dEvent       ,
       Side                   = d.cSide        ,
       OutsideHistoryDate     = convert(nchar, d.devent,112) ,
       Outcome                = p.cOvrClass    ,
       ProcedureType          = cat.ctype      ,
       ProcedureCategoryMajor = cat.cmajor     ,
       ProcedureCategoryMinor = cat.cminor
from      dbo.procrpt rpt
join      dbo.procd   d   on d.iprocrptid   = rpt.iprocrptid
join      dbo.proclu  lu  on lu.iprocluid   = d.iprocluid
join      dbo.pathlgy p   on p.iProcID      = d.iprocid
left join dbo.proccat cat on cat.iproccatid = lu.iproccatid
where procrpt.ipatientid = @iPatientID

我不太明白你的意思。在标准SQL中,内部连接在WHERE子句之前,除非我遗漏了什么。您得到的五个答案几乎完全相同,所以我认为你得到了正确的答案:。值得一看@Andrew:你可以通过语法在WHERE子句中进行内部连接:TABLE_X.X=TABLE_Y.Y。你可以通过语法在WHERE子句中进行左连接:TABLE_X.X=TABLE_Y.Y+@Chris:是的,我觉得很好
这是一个广泛的共识:过滤器位置为-1。我看到很多人被这绊倒了。WHERE子句版本完全符合ISO标准SQL92和更高版本。ANSI是发布ISO标准的机构之一。ANSI SQL真的意味着ISO SQL谢谢。这是编写多个内部联接的一种非常清晰的方法。
SELECT fields
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.t1_id
INNER JOIN table3 t3 ON t1.id = t3.t1_id
    AND
    t2.id = t3.t2_id
SELECT fields
FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.t1_id
INNER JOIN table3 t3 ON t1.id = t3.t1_id
    AND
    t2.id = t3.t2_id
    AND
    t3.id = 3
select PatientID              = rpt.ipatientid ,
       EventDate              = d.dEvent       ,
       Side                   = d.cSide        ,
       OutsideHistoryDate     = convert(nchar, d.devent,112) ,
       Outcome                = p.cOvrClass    ,
       ProcedureType          = cat.ctype      ,
       ProcedureCategoryMajor = cat.cmajor     ,
       ProcedureCategoryMinor = cat.cminor
from      dbo.procrpt rpt
join      dbo.procd   d   on d.iprocrptid   = rpt.iprocrptid
join      dbo.proclu  lu  on lu.iprocluid   = d.iprocluid
join      dbo.pathlgy p   on p.iProcID      = d.iprocid
left join dbo.proccat cat on cat.iproccatid = lu.iproccatid
where procrpt.ipatientid = @iPatientID