繁体   English   中英

SQL子查询返回一列的MIN和另一列的对应值

[英]SQL subquery to return MIN of a column and corresponding values from another column

我正在尝试查询

  1. 通过的课程数量
  2. 最早的课程通过了
  3. 对于当前尚未被开除的每个学生,通过第一门课程所花费的时间。

棘手的部分是2)。 我通过将课程表映射到自身上来构造了一个子查询,但仅将匹配项限制为datepassed = min(datepassed)。 该查询似乎可以用于非常简单的示例,但是当我尝试将其应用于我的完整数据集(将返回约100万条记录)时,执行查询的时间就不可能太长(将其保留2个小时以上,但仍然不会完成)。

有没有更有效的方法可以做到这一点? 感谢您的帮助!

查询:

SELECT 
  S.id,
  COUNT(C.course) as course_count,
  C2.course as first_course,
  DATEDIFF(MIN(C.datepassed),S.dateenrolled) as days_to_first
FROM student S
LEFT JOIN course C 
  ON C.studentid = S.id
LEFT JOIN (SELECT * FROM course GROUP BY studentid HAVING datepassed IN (MIN(datepassed))) C2
  ON C2.studentid = C.studentid
WHERE YEAR(S.dateenrolled)=2013 
  AND U.id NOT IN (SELECT id FROM expelled)
GROUP BY S.id
ORDER BY S.id

学生桌

id  status  dateenrolled
1   graduated   1/1/2013
3   graduated   1/1/2013

驱逐表

id  dateexpelled
2   5/1/2013

课程表

studentid   course  datepassed
1   courseA 5/1/2014
1   courseB 1/1/2014
1   courseC 2/1/2014
1   courseD 3/1/2014
3   courseA 1/1/2014
3   couseB  2/1/2014
3   courseC 3/1/2014
3   courseD 4/1/2014
3   courseE 5/1/2014
SELECT id, course_count, days_to_first, C2.course first_course
FROM (
    SELECT S.id, COUNT(C.course) course_count, 
        DATEDIFF(MIN(datepassed),S.dateenrolled) as days_to_first,
        MIN(datepassed) min_datepassed
    FROM student S
        LEFT JOIN course C ON C.studentid = S.id 
    WHERE S.dateenrolled BETWEEN '2013-01-01' AND '2013-12-31'
        AND S.id NOT IN (SELECT id FROM expelled)
    GROUP BY S.id
) t1 LEFT JOIN course C2 
    ON C2.studentid = t1.id
    AND C2.datepassed = t1.min_datepassed
ORDER BY id

我会尝试类似的东西:

SELECT s.id, f.course,
  COALESCE( DATEDIFF( c.first_pass,s.dateenrolled), 0 ) AS days_to_pass, 
  COALESCE( c.num_courses, 0 ) AS courses
FROM student s
LEFT JOIN
( SELECT studentid, MIN(datepassed) AS first_pass, COUNT(*) AS num_courses
  FROM course
  GROUP BY studentid ) c
ON s.id = c.studentid
JOIN course f
ON c.studentid = f.studentid AND c.first_pass = f.datepassed
LEFT JOIN expelled e
ON s.id = e.id
WHERE s.dateenrolled BETWEEN '2013-01-01' AND '2013-12-31'
AND e.id IS NULL

该查询假设一个学生在给定的一天只能通过一门课程,否则您可以为一个学生获得多个行,因为它可能有很多第一门课程。

为了提高性能,将在学生表中的dateenrolled索引和在课程表中的(studentid,datepassed)索引上综合起来将很有帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM