WHERE(set)IN(set)

时间:2017-01-05 11:10:41

标签: mysql sql

编辑:我似乎错误地问了这个问题。

我正试图找到一种方法来查询一个集合是否在另一个集合中可用。例如:

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),所以不应从桌子上拉出任何东西。

5 个答案:

答案 0 :(得分: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;

(注意:如果给定用户的ID是唯一的,则不需要DISTINCT。)

那么,你可以使用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;

答案 1 :(得分: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
);

答案 2 :(得分: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:

你在这里混淆了一些ID。这将更接近:

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_requirements汇总exercise_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

答案 3 :(得分:0)

你可以用这个

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

或者使用来自@DanFromGermany的EXISTS作为link

答案 4 :(得分:0)

您可以使用Case制作一个Sum,对于每个等级,在1,5和15之间增加1。 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