从 reference/join-table 获取所有 Many:Many 关系
Get all Many:Many relationships from reference/join-table
我在 Many:Many 场景中查询可能的关系时遇到困难。
我展示我的模式:
我做的知道如何用这个模式查询是:
- 给定用户所属的所有乐队。
- 属于给定 Band 的所有用户。
我尝试要做的是:
- 获取给定用户所属的所有个乐队的所有个乐队成员。
- 即,假设我在 5 个乐队中,我想知道我的 所有 乐队成员是谁。
我的第一个问题是:
- 是否有此类查询的名称?我对加入的关系比 what 更感兴趣(只是说这让我想将整个系统放入图形数据库 :/ )?我想学习正确的术语来帮助我 google 解决未来的问题。
- 一般来说,这在 RDBMS 领域是不是一个糟糕的想法?我觉得这应该是一个常见的用例,但我想知道我是否完全接近这个错误。
回顾一下:
- 我正在查询上述模式,预期输出为每个用户一行,作为给定用户与之共享乐队的乐队成员。
术语
您的术语似乎是正确的 - "many to many",通常写成带冒号的 "many:many"。有时中间的table(band_members)被称为"bridge table".
您可能会删除 band_members.id
,因为这两个外键也构成了一个复合主键(而且主键实际上可以这样定义,因为通常 User 不能是同一个的成员Band 两次。唯一的例外是用户可以在同一 Band 中担任多个角色)。
解决方案
从表面上看,这听起来很简单——我们可以看到 table 之间的关系,通常只需在它们之间使用一个 INNER JOIN
。共有三个 table,因此这将是两个联接。
但是,我们必须首先正确地概念化问题。我们遇到的问题是用户和乐队成员(用户 ID)之间的连接实际上用于两件事:
- 哪个用户属于哪个频段
- 按用户过滤
所以要做到这一点,我们需要引入一个具有多种用途的 table:
SELECT
Users.first_name, Users.last_name
FROM Users
INNER JOIN Band_Members Band_Members1 ON (Band_Members1.user_id = Users.Id)
INNER JOIN Band_Members Band_Members2 ON (Band_Members1.band_id = Band_Members2.band_id)
WHERE
Band_Members2.user_id = 1
你可以在这里看到我加入了两次Band_Members
,当一次这样做时,必须给它们起不同的别名,这样它们就可以被单独引用了。第一个实例在用户 table 和网桥 table 之间进行了明显的连接,第二个实例在 "Users who are in Bands" 和 "Bands that I am in" 之间进行了 link。
当然,此解决方案要求您知道自己的用户 ID。如果您想执行类似的查询但根据您的姓名进行过滤,那么您将必须加入用户 table 的另一个(重新别名)副本,以便您可以区分这两个不同的目的: "Users who are in bands" 和 "your User".
我在 Many:Many 场景中查询可能的关系时遇到困难。
我展示我的模式:
我做的知道如何用这个模式查询是:
- 给定用户所属的所有乐队。
- 属于给定 Band 的所有用户。
我尝试要做的是:
- 获取给定用户所属的所有个乐队的所有个乐队成员。
- 即,假设我在 5 个乐队中,我想知道我的 所有 乐队成员是谁。
我的第一个问题是:
- 是否有此类查询的名称?我对加入的关系比 what 更感兴趣(只是说这让我想将整个系统放入图形数据库 :/ )?我想学习正确的术语来帮助我 google 解决未来的问题。
- 一般来说,这在 RDBMS 领域是不是一个糟糕的想法?我觉得这应该是一个常见的用例,但我想知道我是否完全接近这个错误。
回顾一下:
- 我正在查询上述模式,预期输出为每个用户一行,作为给定用户与之共享乐队的乐队成员。
术语
您的术语似乎是正确的 - "many to many",通常写成带冒号的 "many:many"。有时中间的table(band_members)被称为"bridge table".
您可能会删除 band_members.id
,因为这两个外键也构成了一个复合主键(而且主键实际上可以这样定义,因为通常 User 不能是同一个的成员Band 两次。唯一的例外是用户可以在同一 Band 中担任多个角色)。
解决方案
从表面上看,这听起来很简单——我们可以看到 table 之间的关系,通常只需在它们之间使用一个 INNER JOIN
。共有三个 table,因此这将是两个联接。
但是,我们必须首先正确地概念化问题。我们遇到的问题是用户和乐队成员(用户 ID)之间的连接实际上用于两件事:
- 哪个用户属于哪个频段
- 按用户过滤
所以要做到这一点,我们需要引入一个具有多种用途的 table:
SELECT
Users.first_name, Users.last_name
FROM Users
INNER JOIN Band_Members Band_Members1 ON (Band_Members1.user_id = Users.Id)
INNER JOIN Band_Members Band_Members2 ON (Band_Members1.band_id = Band_Members2.band_id)
WHERE
Band_Members2.user_id = 1
你可以在这里看到我加入了两次Band_Members
,当一次这样做时,必须给它们起不同的别名,这样它们就可以被单独引用了。第一个实例在用户 table 和网桥 table 之间进行了明显的连接,第二个实例在 "Users who are in Bands" 和 "Bands that I am in" 之间进行了 link。
当然,此解决方案要求您知道自己的用户 ID。如果您想执行类似的查询但根据您的姓名进行过滤,那么您将必须加入用户 table 的另一个(重新别名)副本,以便您可以区分这两个不同的目的: "Users who are in bands" 和 "your User".