MySQL n:m找到表1中的元素,它们只包含表2中的元素

时间:2016-09-08 14:06:50

标签: mysql sql

我有两个表:segment(id,name)和parts(id,name)。这两个具有n:m关系,因此段可以有多个部分,一个部分可以属于多个部分。

当然,我们有一个链接表segments_parts(segments_id,parts_id)来将这两者连接在一起,这与n:m关系一样习惯。

现在,给定一个部件ID列表,我想检查是否有一个具有这些部分的部分,但没有更多!

因此,如果例如段2具有部分1和3并且段5具有部分1,3和7,当我请求&#34时;给出部分1和3的部分"我只想要返回段2,而不是两者都返回。

Segments                         Parts
------------------------         ------------------------
| ID | Name            |         | ID | Name            |
------------------------         ------------------------
| 1  | Segment 1       |         | 1  | Part 1          |
| 2  | Segment 2       |         | 2  | Part 2          |
| 3  | Segment 3       |         | 3  | Part 3          |
| 4  | Segment 4       |         | 4  | Part 4          |
| 5  | Segment 5       |         | 5  | Part 5          |
------------------------         | 6  | Part 6          |
                                 | 7  | Part 7          |
                                 ------------------------

segments_parts
------------------------
| segment_id | part_id |
------------------------
|     1      |     1   |
|     1      |     4   |
|     2      |     1   |
|     2      |     3   |
|     3      |     2   |
|     3      |     4   |
|     4      |     2   |
|     4      |     3   |
|     5      |     1   |
|     5      |     3   |
|     5      |     7   |
------------------------

给定输入1,3我想要返回段ID 2(因为它是具有这两个部分id的段,没有别的。注意段5也有部分1和3,但也有部分7因此应该不予退还!)

给定输入1,3,7我想要返回段ID 5。

给定输入1,6我不想返回任何内容,因为没有包含这两部分的段。

1 个答案:

答案 0 :(得分:1)

这是set-within-sets查询。我想使用group byhaving来解决这些问题。假设没有重复:

select sp.segment_id
from segments_parts sp
group by sp.segment_id
having <list size> = sum(sp.parts_id in (<your list here>)) and
       <list size> = count(*);

如果你有重复项,那么:

select sp.segment_id
from segments_parts sp
group by sp.segment_id
having <list size> = count(distinct case when parts_id in (<your list here> then parts_id end) and
       <list size> = count(distinct parts_id);

您需要在having子句中添加列表的长度。