从具有多对多关系的表中进行选择

时间:2018-02-13 10:26:45

标签: mysql

我有三个表,一个问题,一个预防措施,以及它们之间的链接之一(problem_pa)。问题可能与多种行为有关,也可能与多种问题采取预防措施,即“多对多”关系。 我想要一个SQL语句,它允许我列出仍然处于“开放”状态的所有问题,这些问题在“打开”状态下没有任何预防措施,即所有操作都已执行和关闭。 我找到了与封闭行动相关的未解决问题(见下文):

SELECT p.id, p.slogan, p.state, pa.id, pa.slogan, pa.state
FROM problems p
JOIN problem_pa pp
ON p.id = pp.problem
JOIN preventative_actions pa
ON pa.id = pp.preventative_action
WHERE p.state = "Open" AND pa.state = "Closed"

但是这只能让我成为一部分,因为多对多关系意味着这些问题可能仍然会有与之相关的开放行为。 如何获得没有剩余未处理操作的打开问题列表(仅关闭操作)?

三张桌子:

行的问题(加上与问题无关的其他行):

id (int(11), AUTO_INCREMENT)
slogan (varchar(255))
state (enum ('Open', 'Closed')

带行的preventative_actions(加上其他不相关的行):

id (int(11), AUTO_INCREMENT)
slogan (varchar(255))
state (enum ('Open', 'Closed')

带有行的problem_pa:

problem (int(11), to hold the id from the problems table)
preventative_action (int(11), to hold the id from the actions table)

问题中的示例数据:

1, Problem number 1, Open
2, Problem number 2, Open
3, Problem number 3, Closed

preventative_actions中的示例数据:

1, Action number 1, Open
2, Action number 2, Closed
3, Action number 3, Closed

problem_pa中的示例数据

1, 1
1, 2
2, 1
3, 2
3, 3

我希望我的搜索返回的是问题ID 3 - 这是唯一一个只有关闭操作链接的问题。但是搜索与闭合动作相关的问题将返回问题ID 1和3.我想我真正想要的是(与开放动作相关的问题)的反转,这将给出上面(ids 1和2)的反转。示例

我在数据库中连接了多达60个操作时遇到问题,其中55个现在已关闭,5个仍处于打开状态。以上是简化,但我认为它包含所有相关数据。

1 个答案:

答案 0 :(得分:2)

此查询返回状态为“打开”且未打开的preventative_actions 至少一个已关闭的preventative_actions 的所有问题。

SELECT p.*
FROM problems p
INNER JOIN problem_pa pp ON pp.problem_id = p.id
INNER JOIN preventative_actions pa ON pa.id = pp.preventative_action_id
WHERE p.state = 'Open'
GROUP BY p.id
HAVING SUM(IF(pa.state = 'Open', 1, 0)) = 0 AND SUM(IF(pa.state = 'Closed', 1, 0)) > 0;