2017-01-05 89 views
1

编辑:我似乎不正确地问这个问题。哪里(设置)IN(设置)

我试图找到一种方法来查询,如果一套在另一套可用。例如:

SELECT * FROM something 
WHERE (1, 3) IN (1, 2, 3, 4, 5) 

在这种情况下,1 & 3是在集合(1,2,3,4,5)。又如:

SELECT * FROM something 
WHERE (1, 3) IN (1, 5, 7, 9); 

在这种情况下,1 & 3在设定不(1,5,7,9),所以没有什么应该从表中可以拉动。

+1

这似乎是问同样的,并已解决了这个此前一天 - [MySQL的多个IN条件与同桌子查询(http://stackoverflow.com/ question/41480785/mysql-multiple-in-conditions-to-subquery-with-same-table) – DanFromGermany

回答

1

新的要求(根据sqlfiddle.com/#!9/f36d92/2):

 
# The goal is to write a query that will select all exercises 
# that the user has the correct equipment for, where the pre-defined 
# set is the id's of the equipment the user has. 

# For example, let's assume the user has equipment (1, 4) 
# The exercise "Curls" should be pulled from the table, as the user has all 
# of the required equipment based on the exercise_requirements table. 
# while "Wrecking Ball" is not returned as the user only has a portion of the 
# required equipment. 

# If the user's equipment was (1, 3, 4) then both "Curls" and "Wrecking ball" 
# would be returned from the exercises table, as the user has the required equipment 
# for both exercises. 

#---- 

#Below is my take on your query. 
SELECT ex.* FROM exercises ex 
WHERE ex.id IN (
    SELECT exercise_id FROM exercise_requirements 
    WHERE ex.id IN (1, 4) 
    GROUP BY exercise_id 
    HAVING COUNT(distinct exercise_id) = 3 
); 

SOLUTION:

您在这里混淆了一些标识。这将更接近:

SELECT ex.* FROM exercises ex 
WHERE ex.id IN (
    SELECT exercise_id FROM exercise_requirements 
    WHERE equipment_id IN (1, 4) 
    GROUP BY exercise_id 
    HAVING COUNT(distinct equipment_id) = 2 
); 

但仍然这个查询是反之亦然。我们不想知道用户的所有设备是否都存在于一套锻炼所需的设备中,但是否需要进行锻炼的整套设备是在用户的设备中找到的。

可能最简单的写法是:合计exercise_requirementsexercise_id并检查没有equipment_id是用户不需要的。

select * 
from exercises 
where id in 
(
    select exercise_id 
    from exercise_requirements 
    group by exercise_id 
    having sum(equipment_id not in (1, 4)) = 0 
); 

您更新小提琴:http://sqlfiddle.com/#!9/f36d92/5

+0

绝对天才。有时候想到盒子外面。我很有决心让“Y号码中的X号码”收集到NOT IN Y号码的总和甚至没有超出我的想法。 – Hobbyist

0

您可以使用此

SELECT u.* 
FROM users u 
INNER JOIN completed_levels cl 
ON cl.user_id = u.id 
WHERE cl.id IN (1, 5, 7); 

或者使用EXISTS作为link从@DanFromGermany

+1

这不起作用,这将返回已完成级别1,5或7的所有用户。查询需要选择用户已经完成了1,5和7级。 – Hobbyist

0

您可以使用Case做出Sum将与1增加1内的每个级别,5 & 7。

SELECT A.* FROM users AS 
INNER JOIN 
(
SELECT U.id, 
SUM(CASE WHEN 
     (
     A.completed_levels = 1 
     OR A.completed_levels = 5 
     OR A.completed_levels = 7 
    ) THEN 1 ELSE 0 END 
    ) AS RN 
FROM completed_levels A 
INNER JOIN users U ON A.user_id = U.id 
GROUP BY U.id 
) B ON A.id = B.id 
WHERE B.RN = 3 -- Those users have completed level 1, 5 & 7 will have RN = 3 only 
+0

我似乎是错误地问了这个问题。我的问题实际上是如何确保所有的集合都包含在不同的集合中。例如,'WHERE(1,5)IN(1,2,3,4,5,6,7)'是真的,'WHERE(1,5)IN(1,2,4,7, 8)'会是假的。查询需要动态构建,所以我试图避免一堆'AND'调用。 – Hobbyist

1

您正在使用IN子句相关的子查询(即,子查询引用u.id)。这不是我们如何使用它。 IN子句适用于不相关的子查询;如果您需要相关子查询,请改用EXISTS。对于您的问题,非相关子查询就足够了,所以用IN相应:

select * 
from users 
where u.id in (select user_id from completed_levels where id in (1, 5, 7); 

如果用户必须拥有所有级别:

select * 
from users 
where u.id in (select user_id from completed_levels where id = 1 
    and u.id in (select user_id from completed_levels where id = 5 
    and u.id in (select user_id from completed_levels where id = 7; 

这样的问题通常是更好地与聚集,从而解决不必一次又一次查询同一表:

select * 
from users 
where u.id in 
(
    select user_id 
    from completed_levels where id in (1, 5, 7) 
    group by user_id 
    having count(distinct id) = 3 
); 
+0

我似乎不正确地问了这个问题。我的问题实际上是如何确保所有的集合都包含在不同的集合中。例如,WHERE(1,5)IN(1,2,3,4,5,6,7)为真,WHERE(1,5)IN(1,2,4,7,8)为是假的。查询需要动态构建,所以我试图避免一堆AND调用。 – Hobbyist

+0

好的,我现在明白了。请看我更新的答案。 –

+0

请检查我的评论中反映的问题编辑。 +1为不正确问题的答案。 – Hobbyist

4

注意:这回答了原来的问题,这似乎与OP修改后的问题无关。

你可以得到谁完成所有三个级别使用的用户:

SELECT cl.user_id 
FROM completed_levels cl 
WHERE cl.id IN (3, 5, 7) 
GROUP BY cl.user_id 
HAVING COUNT(DISTINCT cl.id) = 3; 

(注:DISTINCT是没有必要的,如果给定用户的ID是唯一的)

然后,您可以得到你想要使用JOIN或类似的结构是什么:

SELECT u.* 
FROM users u JOIN 
    (SELECT cl.user_id 
     FROM completed_levels cl 
     WHERE cl.id IN (3, 5, 7) 
     GROUP BY cl.user_id 
     HAVING COUNT(DISTINCT cl.id) = 3 
    ) cu 
    ON cl.user_id = u.id; 
+0

ahhh !!总是解决方案自带@Gordon ... – Esty

+0

真的,@Gordan有智力回答。致敬&+1 – Susang

+0

嘿@Gordon,谢谢你的回答,我似乎在您点击发送后立即发布我的编辑内容,您是否介意查看问题编辑?我在没有意识到的情况下提出了错误的问题,或者更确切地说是错误地提出了问题 谢谢。 – Hobbyist