MYSQL:从多对多链接表中选择

时间:2015-07-07 00:24:13

标签: mysql many-to-many

我有3张桌子:

1)运动:exercise_id,名称

2)设备:equipment_id,名称

3)exercise_equipment:exercise_id,equipment_id - 这是练习和装备之间的链接表。在此表中,一项练习可能需要多件设备,并且相同的设备可用于许多练习。

CREATE TABLE exercise
    (`ex_id` int, `name` varchar(30))
;   
INSERT INTO exercise
    (`ex_id`, `name`)
VALUES
    (1, 'push ups'),
    (2, 'sit ups'),
    (3, 'squats'),
    (4, 'push ups with a fitness ball')
;

CREATE TABLE equipment
    (`eq_id` int, `name` varchar(30))
;
INSERT INTO equipment
    (`eq_id`, `name`)
VALUES
    (1, 'none'),
    (2, 'mat'),
    (3, 'ball')
;

CREATE TABLE exercise_equipment
    (`ex_id` int, `eq_id` int)
;
INSERT INTO exercise_equipment
    (`ex_id`, `eq_id`)
VALUES
    (1, 2),
    (2, 2),
    (3, 1),
    (4, 2),
    (4, 3)
;

我需要做的是选择用户可以使用他所拥有的设备进行的所有练习(例如,1和2 - 没有设备或垫子)。

我找到了一些示例,并尝试使用内部联接进行以下查询,其中包含:

SELECT ex.ex_id, ex.name from exercise ex 
LEFT JOIN exercise_equipment exeq ON ex.ex_id = exeq.ex_id 
WHERE exeq.eq_id IN (1,2);

select ex_id, name from exercise 
where ex_id in (select ex_id from exercise_equipment where eq_id in (1,2));

但是他们会返回所有练习,而不仅仅是前三个练习。在这种情况下,如果用户想要进行不需要任何设备或垫子的练习(1和2),我想要返回俯卧撑,仰卧起坐和深蹲,而不是用球进行垫练习。

我希望我的解释清楚。我真的很感激我能得到的任何帮助!

1 个答案:

答案 0 :(得分:0)

您希望练习仅使用 1和2.当您使用WHERE子句时,您将过滤掉所有其他设备,因此无效。

相反,您需要聚合并检查是否没有其他设备用于整个练习。这是一个类似的查询,带有HAVING子句:

SELECT ex.ex_id, ex.name
FROM exercise ex LEFT JOIN
     exercise_equipment exeq
     ON ex.ex_id = exeq.ex_id 
GROUP BY ex.ex_id, ex.name
HAVING SUM(exeq.eq_id NOT IN (1, 2)) = 0;

如果某些练习完全没有设备,您可能需要:

HAVING COALESCE(SUM(exeq.eq_id NOT IN (1, 2)), 0) = 0;