SQL问题:链接表时WHERE / INNER JOIN子句的顺序重要吗?

时间:2019-05-21 11:13:02

标签: sql inner-join where

考试问题(AQA A级计算机科学):
[星号显示的主键]

Athlete(*AthleteID*, Surname, Forename, DateOfBirth, Gender, TeamName)
EventType(*EventTypeID*, Gender, Distance, AgeGroup)
Fixture(*FixtureID*, FixtureDate, LocationName)
EventAtFixture(*FixtureID*, *EventTypeID*)
EventEntry(*FixtureID*, *EventTypeID*, *AthleteID*)
     

应列出所有参加比赛的运动员的名单   那是在18/09/09发生的该列表必须包括姓,名和   这些运动员的出生日期,无其他详细信息。该清单应显示在   按姓氏的字母顺序。

     

编写SQL查询以生成列表。

我知道您可以通过两种方式执行此操作,一种使用WHERE子句,另一种使用INNER JOIN子句。但是,我想知道链接表时顺序是否重要。

第一个示例解决方案:

SELECT Surname, Forename, DateOfBirth
FROM Athlete, EventEntry, Fixture
WHERE FixtureDate = "17/09/2018"
 AND Athlete.AthleteID = EventEntry.AthleteID
 AND EventEntry.FixtureID = Fixture.FixtureID
ORDER BY Surname

这是第一个示例性解决方案,如果我要在WHERE子句中切换表的顺序是否仍然正确,例如:

WHERE FixtureDate = "17/09/2018"
AND EventEntry.AthleteID = Athlete.AthleteID
AND Fixture.FixtureID = EventEntry.FixtureID

我对INNER JOIN子句有相同的问题,这是第二个示例解决方案:

SELECT Surname, Forename, DateOfBirth
FROM Athlete 
INNER JOIN EventEntry ON Athlete.AthleteID = EventEntry.AthleteID 
INNER JOIN Fixture ON EventEntry.FixtureID = Fixture.FixtureID
WHERE FixtureDate = "17/09/2018"
ORDER BY Surname

再次,如果我改用以下顺序,那会正确吗:

INNER JOIN EventEntry ON Fixture.FixtureID = EventEntry.FixtureID

如果顺序很重要,那么有人可以向我解释为什么是示例中显示的顺序吗?

3 个答案:

答案 0 :(得分:2)

一些建议:

  • 从不FROM子句中使用逗号。 始终使用正确的,明确的,标准 JOIN语法。
  • 使用表别名的缩写。
  • 使用标准日期格式!
  • 限定所有列名称。

然后,比较的顺序对于相等性并不重要。我建议使用规范排序。

因此,查询应更像:

SELECT a.Surname, a.Forename, a.DateOfBirth
FROM Athlete a INNER JOIN
     EventEntry ee
     ON a.AthleteID = ee.AthleteID INNER JOIN
     Fixture f
     ON ee.FixtureID = f.FixtureID
WHERE a.FixtureDate = '2018-09-17'
ORDER BY a.Surname;

我猜测SELECT中的所有列都来自Athlete。如果不正确,请调整表别名。

答案 1 :(得分:0)

SQL有许多样式约定,@ gordonlinoff的答案提到了一些多年生的约定。

您的问题有几个答案。

最重要的是(从概念上来说)SQL是declarative language-您告诉它您想要它做什么,而不是如何去做。在过程语言(如C,Java或PHP)中,执行顺序确实很重要-指令序列是过程的一部分。用声明性语言,顺序并不重要。

并非总是如此-出于性能原因,较早的查询优化器似乎更喜欢语句中较早的where子句。几十年来我还没有看到它,所以假设那不是真的。

因为顺序无关紧要,但是正确理解查询的意图确实重要,因此许多SQL开发人员都强调可读性。这就是为什么我们喜欢显式联接语法和有意义的别名的原因。为了提高可读性,说明顺序可能会有所帮助。我倾向于从“最重要的”表开始,通常是从中选择大多数列的表,然后按照逻辑顺序从一个表到下一个表进行联接。这样可以更容易地遵循逻辑。

答案 2 :(得分:0)

使用内部联接时,只要先决条件表在上方/之前,顺序就无关紧要。在您的示例中,两个联接都从表Athlete开始,因此顺序无关紧要。但是,如果从EventEntry(出于任何原因)开始找到此查询,那么您必须在第一个内部加入运动员,否则您将无法加入Fixture。根据建议,最好使用标准联接语法,并且最好将所有内部联接放在所有左边。如果您不能这样做,则需要进行检查,因为您需要放在内部联接组内部的左侧可能会像内部联接一样工作。那是因为下面的内部使用左表,否则您可以将其放置在内部块的下方。因此,当为null时,左边的行会没问题,但下面的内部会剪切记录。

但是,当以上情况不存在/影响顺序并且所有内部联接可以按任意顺序放置时,仅性能很重要。通常,基数高的表的性能更好,而在某些情况下,相反的表效果更好。因此,如果订购是免费的,则可以尝试提高基数表的订购量或降低订购量(反之则更快)。

澄清:作为先决条件表,我按条件调用了联接表所需的表:...在[whatever]上联接B在c.id = b.cid上联接C-这里表B是表C的先决条件。 / p>

我之所以提到左联接,是因为尽管问题是关于内部顺序的,但当联接混合在一起时(内部和左联接),那么单独的联接顺序就很重要了(以上所述),因为这可能会影响查询逻辑: ... [在任何位置]上的B联接在c.id = b.cid上的C联接在D.id = C.did的D联接 在上面的示例中,左联接潜入内部联接顺序。我们不能在D之后排序,因为它是D的先决条件。但是对于条件c.id = b.cid不为真的记录,整个B表行都为空,然后整个结果行(B + C + D)关闭由于以下内部联接的D.id = C.did条件而导致结果。此示例需要检查,因为以下(内部下一个)内部联接会蒸发掉左联接的目的。最后,内部连接的顺序在与左侧混合时最好放在顶部,而不会干扰任何左侧连接。