我可以跳过连接中的中间表吗?

Eud*_*des 7 join sql-server

我写了这个查询:

SELECT 
    "BD - Utilizadores".Utilizador, 
    "BD - Utilizadores"."Palavra passe", 
    "BD - Áreas".área 
FROM "BD - Utilizadores" 
INNER JOIN "BD - Permissões" 
    on "BD - Utilizadores".id = "BD - Permissões"."user_id" 
Join "BD - Áreas" 
    on "BD - Permissões".area_id = "BD - Áreas".id
Run Code Online (Sandbox Code Playgroud)

我想将表“bd - utilizadores”中的数据与“bd - áreas”连接起来。由于他们没有直接联系,我不得不使用“中间人”,即“bd - Permissões”。这是图表:

链接表

我的主要问题是,有没有其他方法可以做到这一点并获得相同的结果?

小智 10

tl;博士

最简洁的答案是不。您必须进行多重连接,即使您只需要“每一侧”的两个表中的列。

餐桌设计

这看起来很痛苦,但尽管它使您的查询更长,但获得正确的数据库结构(包括外键)比使查询更短更重要。

有几种排列外键的方法,有时还有额外的表,这些表仅用于表达关系。例如,如果每只猫都有一个唯一的鼠标,则可能有一个从猫到鼠标的具有唯一约束的外键。它甚至可以是 Cat 的主键。如果每只猫都有零个或多个老鼠,但没有老鼠有超过一只猫,那么您将有一个从老鼠到猫的常用外键。如果每只猫有零个或多个鼠标,并且每个鼠标有零个或多个猫,则您将创建第三个表 CatMouseMatching,该表为 Cat 和鼠标之间的每个“边”都有一个条目,并带有指向 Cat 和鼠。您将了解到这些模式非常重要,并且基本案例涵盖了很多情况。

现在,假设您反转了表设计中的外键,因此UtilizadorsAreas都有指向 的外键Permissoes。这意味着您可以简化连接 - 因为您可以过滤permissoe_id两个表中的相等性。然而,这将是Utilizador和之间的一种非常奇怪的关系Area,可能与现实不符。您可能有一个Utilizador与 aPermissoe没有任何Area链接的关联。这Utilizador将从内部联接中消失。

这可能只有在有一些真实的实体形成两个实体之间的联系时才有意义。例如,每只猫都住在一个房子里,每只老鼠都住在一个房子里。你可以很容易地找到住在同一个房子里的猫老鼠对。

实用技巧

您总是可以创建一个 VIEW,这使得一个常见的查询表现得像一个表。上面的查询可以定义为视图,然后其他查询可以从中选择并加入它,而无需了解内部由哪些联接构成视图。

如果您不创建视图,您至少可以保存执行连接的代码片段,以便您稍后可以将其粘贴到其他类似的查询中。

  • 我需要更多地研究关系,还有很多,你能把我链接到一篇关于关系的好论文吗?并感谢您的帮助。我会阅读并重新(阅读)您的解释,以便我能够完全理解这个概念。 (2认同)

Dav*_*ett 6

如果这是您想要的结果(为区域用户设置的所有权限组合),则否。

如果您要列出具有各自权限的所有区域和用户,包括未设置权限的位置,那么您需要CROSS JOIN列出这些表,然后LEFT OUTER JOIN列出两者的权限表。

附带说明:如果它是其他人的数据库,它可能超出您的控制范围,但我会尽可能避免表名中的空格,以及非 ANSI 字符。这将使代码更易于阅读(尽管这当然是主观意见),避免使用引号或括号对名称进行转义的需要,并且如果您需要使用不支持此类内容的工具访问数据库,则稍后会减少问题在名称中或需要将数据库迁移到另一个没有的平台。


Mic*_*een 5

我认为您可能混淆了语法和语义。在类型兼容的任何列上连接任何两个表在语法上是正确的。例如,您可以在 上加入 Utilizadores 和 Áreas email = area。这样做是合法的 SQL,但它毫无意义。换句话说,句法上有效但语义上无效。

Permissões 表的存在是有原因的。它的存在记录了意义。该表中的一行出于某种原因将用户连接到一个区域可能是用户管理该区域,或向该区域销售或被禁止进入该区域或任何其他可能性。您的数据库模型将确定其含义的实际情况。可能有多种原因将两个事物结合起来,这些原因应该单独建模。以一个人和一辆车为例。同一个人可能是汽车的注册车主,他可能已经付款并且可能正在驾驶它。这是三个不同的事实,然而,没有一个暗示另一个,每个都有不同的语义,应该单独建模。

通过加入 Permissões,您将使用该表中内置的语义。任何其他连接将具有不同的语义,因此即使它返回相同的值,它也会具有不同的含义,因此不会等效。