表学期:
semesterID startDate
1 2013-01-01
2 2013-03-01
3 2013-06-01
表类:
classID class_title semesterID
1 Math 1
2 Science 1
3 Math 2
4 Science 2
5 Math 3
6 Science 3
表人:
personID firstName lastName
1 John Jones
2 Steve Smith
表class_person:
classID personID
1 1
2 1
5 1
6 1
3 2
4 2
5 2
6 2
我需要获得所有人的列表,第一个学期他们参加了一个班级(学期最早的startDate)。
firstName, lastName, semesterID, startDate
John Jones 1 2013-01-01
Steve Smith 2 2013-03-01
我花了好几个小时试图解决这个问题。这是我得到的最接近的(虽然它根本不是很接近!):
SELECT p.firstName, p.lastName, MIN(s.startDate) AS min_startDate
FROM semesters s
INNER JOIN classes c ON s.semesterID = c.semesterID
INNER JOIN class_person cp ON cp.classID = c.classID
INNER JOIN persons p ON p.personID = cp.personID
GROUP BY cs.personID
ORDER BY min_startDate, p.lastName, p.firstName
任何帮助都会受到大力赞赏。谢谢。
答案 0 :(得分:1)
你最终可能会使用类似下面的怪物(fiddle):
select persons.firstName, persons.lastName,
semesters.semesterID, semesters.startDate
from persons, semesters,
(select p.personID,
(select semesters.semesterID
from semesters, classes, class_person
where semesters.semesterID = classes.semesterID
and classes.classID = class_person.classID
and class_person.personID = p.personID
order by semesters.startDate
limit 1) as semesterID
from (select distinct personID from class_person) as p
) as ps
where persons.personID = ps.personID
and semesters.semesterID = ps.semesterID
子查询p
标识所有人。对于每个,ps
将包含一行。简单地复制personID
,其semesterID
由子查询计算,子查询按日期对学期进行排序,但返回ID。最外面的查询然后重新添加日期。
如果你真的不需要semesterID
,你可以避免使用一层。如果您的学期有序,即他们的ID与startDates的顺序相同,那么您可以简单地使用单个查询,就像您自己的一样,并返回min(semesterID)
和min(startDate)
。
总的来说,这个问题让我想起了很多我自己的问题,Select one value from a group based on order from other columns。答案表明这里也可能适用。特别是,有一些使用用户变量的方法,我仍然感到不舒服,但这将使整个混乱很多更容易,并且似乎工作得很好。因此,调整this answer,您会收到类似这样的查询(fiddle):
SELECT p.firstName, p.lastName, s2.semesterID, s2.startDate
FROM persons p
INNER JOIN (
SELECT @rowNum:=IF(@personID=cp.personID,@rowNum+1,1) rowNum,
@personId:=cp.personID personID,
s.semesterID, s.startDate
FROM (SELECT @personID:=NULL,@rowNum:=0) dummy
INNER JOIN semesters s
INNER JOIN classes c ON s.semesterID = c.semesterID
INNER JOIN class_person cp ON cp.classID = c.classID
ORDER BY cp.personID, s.startDate
) s2 ON p.personID = s2.personID
WHERE s2.rowNum = 1
我会将其他答案作为练习。