假设我有一个'用户'和'课程'表和这两个表与“用户课程”相关联。表。这允许1个用户有许多课程等。
我的用户表包含100万用户,我想:
我接触这种方式的方法是选择性别和年龄与我要求的用户相匹配的用户,这很容易。
接下来,我执行LEFT JOIN并使用子查询,我得到所有用户的数量以及与给定用户共同的课程数量。
问题是,在子查询中,我必须重新选择所有用户而不重复性别='女性' AND birth_year BETWEEN' 1991' AND' 1993'在子查询中,它将选择所有100万用户。
SELECT u . *, matching_courses_count FROM users u LEFT JOIN (SELECT COUNT(course_id) AS matching_courses_count, uc.user_id FROM users u LEFT JOIN user_courses uc ON u.id = uc.user_id WHERE uc.course_id IN (SELECT course_id FROM user_courses WHERE user_id = 1) AND uc.user_id != 1 GROUP BY uc.user_id) matching_courses ON u.id = matching_courses.user_id WHERE gender = 'female' AND birth_year BETWEEN '1991' AND '1993'
SQL小提琴:http://sqlfiddle.com/#!2/c36b8/3
有没有办法可以实现这一点,而无需在子查询中重复选择用户或不必在子查询中重复where子句?
答案 0 :(得分:0)
这是一种使用select
子句中的相关子查询来制定查询的方法。这可以确保您获得满足where
条件的所有用户,即使没有匹配的课程也是如此。
select u.*,
(select count(*)
from user_courses uc join
user_courses uc1
on uc.course_id = uc1.course_id and
uc.user_id = u.id and
uc1.user_id = 1
) as matching_courses_count
from users u
where u.gender = 'female' and
birth_year BETWEEN 1991 AND 1993;
相关子查询只计算用户和用户1之间的课程数量。
答案 1 :(得分:0)
我认为你想要的就是这样完成的。我们的想法是,您选择您感兴趣的用户。然后您将获得他们所学的课程。然后你从课程表中获得具有相同课程ID的其他行,最后你抓住那些参加这些课程的用户。
在where子句中,您可以将结果限制为具有所需条件的用户。并筛选出用户1和2相同的结果。
select *
from users u1
left join user_courses uc1
on u1.id = uc1.user_id
left join user_courses uc2
on uc2.course_id = uc1.course_id
left join users u2
on uc2.user_id = u2.id
where u1.id = 1 and
u2.gender = 'female' and u2.birth_year between '1991' and '1993' and
u1.id != u2.id
然后你可以将这个结果包装在另一个查询中,以便像这样进行相应的课程计数:
select id, count(*) from (
select uc1.course_id, u2.id
from users u1
left join user_courses uc1
on u1.id = uc1.user_id
left join user_courses uc2
on uc2.course_id = uc1.course_id
left join users u2
on uc2.user_id = u2.id
where u1.id = 1 and
u2.gender = 'female' and u2.birth_year between '1991' and '1993' and
u1.id != u2.id) as x
group by id