【问题标题】:Difference between Where and Join on IdWhere 和 Join on Id 的区别
【发布时间】:2019-08-22 22:13:34
【问题描述】:

我最近看到了这个查询,它找到了客户可以去的所有聚会:

SELECT *
FROM Party
    INNER JOIN Organizer on Organizer.OrganizerId = Party.OrganizerId
    LEFT JOIN Client on Client.ClientID = 1
    LEFT JOIN PartyRegistration on PartyRegistration.PartyId = Party.PartyId
WHERE Party.OrganizerId = 0
    AND (Party.HasGuestList = 0 OR PartyRegistration.ClientId = Client.ClientId)

我以前从未见过针对特定值的联接。看到这样的SQL代码正常吗?

我对左连接了解不多,但它可以应用于任何连接,例如,这将如何:

SELECT *
FROM Party
    INNER JOIN Organizer on Organizer.OrganizerId = 0

比较结果是一样的:

SELECT *
FROM Party
    INNER JOIN Organizer on Organizer.OrganizerId = Party.OrganizerId
WHERE Organizer.OrganizerId = 0

【问题讨论】:

  • 如果您与替代方案进行比较,这只能是一个好/坏的做法。将测试放在左连接上与在哪里做两件不同的事情——所以这不是好/坏做法的问题。这可能是XY question。如果您想了解替代方案,请提供minimal reproducible example。但如果是这样的话,首先谷歌常见问题解答重新在左连接与哪里进行测试。
  • 您的评论有何意义? PS再次--“正常”为了什么--实现什么
  • 您已经草率地得出结论,或者没有通过“坏”的措辞提出您想要的问题 - 除非有替代方案,否则不会有不好的做法。想想你真正想问的问题。
  • 您添加的代码从左连接切换到内连接。它做了一些不同的事情。它提出了一个不同的问题。如果您不了解连接的工作原理,请研究一下,如果您遇到困难,请询问有关理解某些权威演示的问题。 PS 对于内部连接,您可以在其中添加条件。一个常见问题。对于左连接,您不能。一个常见问题。在左连接删除任何由空值扩展的行之后,内连接或需要右表列不为空的地方,即仅在行上留下内连接,即“将外连接变为内连接”。一个常见问题。
  • 请在每个帖子中提出一个问题。但它们都是常见问题解答——您是否可以以及何时应该使用 on 与 where 用于内部和外部连接。在考虑发布之前,请始终在谷歌上搜索您的错误消息或您的问题/问题/目标的许多清晰、简洁和精确的措辞,有或没有您的特定字符串/名称,并阅读许多答案。如果您发布问题,请使用一个短语作为标题。请参阅How to Ask 和投票箭头鼠标悬停文本。

标签: sql join syntax left-join where


【解决方案1】:

这是一个很好的做法——事实上,你不能(轻易地)在WHERE 子句中得到这个逻辑。

LEFT JOIN 返回第一个表中的所有行 -- 即使第二个表中没有匹配项。

因此,这将返回前面表格中的所有行——以及来自Client 的所有行,其中ClientId = 1。如果该 ClientId 上没有匹配项,则列将为 NULL,但不会过滤行。

【讨论】:

  • 这是否意味着删除WHERE Party.OrganizerId = 0 以将id 放在INNER JOIN on 条件中也是一种好习惯?
  • @Halhex 这不是一个好习惯的问题,而是一个正确或错误结果的问题。在所有左连接之后使用内部连接,您可以选择在哪里或在哪里进行测试,因此坏/好的做法变得相关。阅读此答案的第一行。 (看看我的回答。)
  • @Halhex 。 . .那是风格问题。我想大多数人会将过滤条件放在where 子句中。 on 子句中的过滤是不同的——如果你将条件移动到 where 它会改变结果。
【解决方案2】:

确实如此。在特定值上左连接是非常糟糕的做法。但有时,我们可能需要一张表中的所有列,尽管我们没有要连接的公共列,并且需要通过特定条件(如 A="some value")进行连接。在这种情况下,在特定条件下添加 LEFT JOIN 是不好的做法,虽然我们可以有更好的方法,下面是更新的代码,如果您有任何问题,请告诉我,我很乐意为您提供帮助。

SELECT *
FROM Party
    INNER JOIN Organizer on Organizer.OrganizerId = Party.OrganizerId
    LEFT JOIN Client USING(CLIENTID)
    LEFT JOIN PartyRegistration on PartyRegistration.PartyId = Party.PartyId
WHERE CLIENTID=1 AND Party.OrganizerId = 0
    AND (Party.HasGuestList = 0 OR PartyRegistration.ClientId = Client.ClientId)

【讨论】:

  • 尝试使用USING 我收到此错误消息 ClientId 不是可识别的表提示选项。如果它打算作为表值函数或 CHANGETABLE 函数的参数,请确保您的数据库兼容模式设置为 90
  • 我的错,我错过了添加表别名。试试这样,Client.ClientID
  • 我也有错误An expression of non-boolean type specified in a context where a condition is expected in the USING.
  • 如果这是左连接条件,这意味着他们想要该条件下的内连接行加上不匹配的左表行,那么这就是左连接条件。
【解决方案3】:

如果您与替代方案进行比较,这只能是好/坏做法的问题。将测试放在 left join on 与 where 做两件不同的事情 - 所以这不是好/坏做法的问题。

如果这是 正确 左连接条件,这意味着您想要在该条件下的内连接行加上不匹配的左表行,那么这就是左连接条件。它不会去其他任何地方。

了解什么是左连接返回:行内连接加上由空值扩展的不匹配左表行。作为左连接的一部分,始终知道您想要什么样的内连接。

【讨论】:

  • 这是什么意思??正如问题所暗示的那样,与将 id 置于 where 条件相比。
  • “不良做法”与什么相比? “在 where 条件下拥有 id”做一些不同的事情,所以如果在 on 中是正确的,那么将它放在 where 所以 where 是 错误甚至不是一个选择。 为什么它在 - 以便我们可以与实际选项进行比较 - 替代方案可以做任何你想做的事情。
  • 这如何回答我的问题?这是“了解返回时的左连接:行上的内连接加上由空值扩展的不匹配的左表行”。试图解释左连接? “总是知道作为左连接的一部分你想要什么内连接”是什么意思?意思是?为什么你这么坚持,却没有什么意义?
  • 您的原始问题涉及左连接。你不明白它是如何工作的,或者你不会问你的问题。所以我告诉你找出答案,并给出一个快速但正确的定义。从给出的定义中可以清楚地看出,因为它是就内部联接而言,您需要知道与外部联接相关联的内部联接;我只是强调一下。您添加的代码是关于 inner join on vs where。它提出的问题与您答案的第一部分不同。你花了很多无益的时间抱怨,而不是试图理解我想要传达的信息。
  • 需要先了解我误解的内容才能理解您的答案。这是无益的。尽管我现在可以看到混乱,因为我确实认为将 on 条件移动到相同的位置,无论连接类型如何,我认为这个答案实际上对这个问题没有用处。主要看戈登的答案,这些答案是实际答案。我的“抱怨”是我试图理解的,如果说我应该去其他地方看看,为什么还要回答呢?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 2011-02-12
相关资源
最近更新 更多