从子查询中访问主表数据

时间:2014-08-09 12:48:51

标签: mysql sql

假设我有一个'用户'和'课程'表和这两个表与“用户课程”相关联。表。这允许1个用户有许多课程等。

我的用户表包含100万用户,我想:

  • 选择特定年龄和性别的用户 AND
  • 选择与其他特定用户共同的精确课程计数

我接触这种方式的方法是选择性别和年龄与我要求的用户相匹配的用户,这很容易。

接下来,我执行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子句?

2 个答案:

答案 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