多对多到多对多:是否需要中间联接?

时间:2019-02-07 09:41:03

标签: mysql many-to-many

将问题简化为基本概念,我们有三个表 components programs users ,它们之间存在多对多关系两个中间表 program_components user_programs

simplified table structure

users
- id (primary key)
- (...)

user_programs
- user_id (foreign key to users id)
- program_id (foreign key to programs id)

programs
- id (primary key)
- (...)

program_components
- program_id (foreign key to programs id)
- component_id (foreign key to components id)

components
- id (primary key)
- (...)

我们正在将用户对程序组件的权限集成到我们的云管理系统中。我在查询中偶然发现了一个接一个的连接,并且想知道是否需要中间表。

SELECT users.id, components.id FROM components
JOIN program_components ON c.id = program_components.component_id
JOIN programs ON program_components.program_id = programs.id
JOIN user_programs ON programs.id = user_programs.program_id
JOIN users ON user_programs.user_id = users.id
WHERE (...)

中间连接是否必要,或者我们可以简化为

SELECT users.id, components.id FROM components
JOIN program_components ON c.id = program_components.component_id
JOIN user_programs ON program_components.programId = user_programs.programId
JOIN users ON user_programs.user_id = users.id
WHERE (...)

从我的测试中,它们都产生相同的数据集,这是我完全期望的。 问题更多是关于MySQL期望得到什么,以及从数据库角度来看哪个查询有意义

出于可读性考虑,我建议第一个版本带有额外的JOIN,因为它通过通用的 programs 表促进了跨多个表进行联接的意图。但是,经常有人告诉我,太多的连接通常是处理问题的错误方法。 [1]

文档中是否有针对此类查询的建议?


[1]我们正在重构,以包括一个适当的user_components表,该表将为我们免除这些查询的使用,并为我们提供了更大的灵活性,但这不在问题的范围之内。

1 个答案:

答案 0 :(得分:0)

由于只需要用户和组件表中的ID,因此没有理由加入程序表。实际上不建议这样做,因为这可能会导致明显的性能下降。

在编写SQL查询时,检查多少行总是有用的。通过加入程序表,即使您不需要任何信息,也必须检查它的ID行。

有关更多信息,您可能有兴趣阅读this,其中介绍了一些提高查询性能的方法