让学生的课程在同一行的查询
Query that gets students with their courses in same row
我需要一个查询来获取获得课程 1、课程 2 和课程 3 的学生。我可以这样查询:
SELECT k.name as firstname, k.surname as lastname, k.Email
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
WHERE dn.CourseID IN
(SELECT CourseID FROM Courses WHERE CourseName IN ('Course1','Course2','Course3'))
但我需要这样的结果集:姓名、姓氏、电子邮件、课程 1、课程 2、课程 3。一个学生没有多行,一行,如果学生获得该课程,则写课程名称。
事实上,我可以想象如何编写该查询(使用子选择),想知道更好的选择。
您可以使用 PIVOT
table 运算符来执行此操作,如下所示:
WITH CTE
AS
(
SELECT
k.name as firstname,
k.surname as lastname,
k.Email,
c.CourseName, c.CourseID
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
INNER JOIN Courses c ON dn.CourseID = c.CourseID
WHERE c.CourseName IN ('Course1','Course2','Course3')
)
SELECT *
FROM CTE AS c
PIVOT
(
MAX(CourseID)
FOR CourseName IN ([Course1], [Course2], [Course3])
) u;
请注意, 由于您没有其他列显示在每个学生的每列课程下,此查询将为每门课程显示 CourseID
值姓名,null
如果学生没有这门课程。您应该选择显示更合适的列,例如标记:
WITH CTE
AS
(
SELECT
k.name as firstname,
k.surname as lastname,
k.Email,
c.CourseName, dn.Mark
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
INNER JOIN Courses c ON dn.CourseID = c.CourseID
WHERE c.CourseName IN ('Course1','Course2','Course3')
)
SELECT *
FROM CTE AS c
PIVOT
(
MAX(Mark)
FOR CourseName IN ([Course1], [Course2], [Course3])
) u;
这会给你:
| firstname | lastname | Email | Course1 | Course2 | Course3 |
|-----------|----------|-------|---------|---------|---------|
| StudentA | test | test | 19 | 20 | 15 |
| StudentB | test | test | 16 | 17 | 20 |
| StudentC | test | test | 20 | 19 | 15 |
另请注意,您应该注意在锚查询中选择的列:
...
SELECT
k.name as firstname,
k.surname as lastname,
k.Email,
c.CourseName, dn.Mark
...
因为 PIVOT
table 运算符将按除您列出并用于透视的列之外的所有列进行分组:
MAX(CourseID)
FOR CourseName IN
因此在您的情况下,它将按 firstname, lastname, Email
.
分组
我认为您可以使用比您更好的查询并使用 MAX(CASE ...)
来实现您的预期结果,如下所示:
SELECT k.name as firstname, k.surname as lastname, k.Email,
MAX(CASE WHEN c.CourseName = 'Course1' THEN 'Yes' ELSE 'No' END) As Course1,
MAX(CASE WHEN c.CourseName = 'Course2' THEN 'Yes' ELSE 'No' END) As Course2,
MAX(CASE WHEN c.CourseName = 'Course3' THEN 'Yes' ELSE 'No' END) As Course3
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
JOIN Courses c ON c.CourseID = dn.CourseID AND c.CourseName Like 'Course[1-3]'
GROUP BY k.name, k.surname, k.Email;
我需要一个查询来获取获得课程 1、课程 2 和课程 3 的学生。我可以这样查询:
SELECT k.name as firstname, k.surname as lastname, k.Email
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
WHERE dn.CourseID IN
(SELECT CourseID FROM Courses WHERE CourseName IN ('Course1','Course2','Course3'))
但我需要这样的结果集:姓名、姓氏、电子邮件、课程 1、课程 2、课程 3。一个学生没有多行,一行,如果学生获得该课程,则写课程名称。
事实上,我可以想象如何编写该查询(使用子选择),想知道更好的选择。
您可以使用 PIVOT
table 运算符来执行此操作,如下所示:
WITH CTE
AS
(
SELECT
k.name as firstname,
k.surname as lastname,
k.Email,
c.CourseName, c.CourseID
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
INNER JOIN Courses c ON dn.CourseID = c.CourseID
WHERE c.CourseName IN ('Course1','Course2','Course3')
)
SELECT *
FROM CTE AS c
PIVOT
(
MAX(CourseID)
FOR CourseName IN ([Course1], [Course2], [Course3])
) u;
请注意, 由于您没有其他列显示在每个学生的每列课程下,此查询将为每门课程显示 CourseID
值姓名,null
如果学生没有这门课程。您应该选择显示更合适的列,例如标记:
WITH CTE
AS
(
SELECT
k.name as firstname,
k.surname as lastname,
k.Email,
c.CourseName, dn.Mark
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
INNER JOIN Courses c ON dn.CourseID = c.CourseID
WHERE c.CourseName IN ('Course1','Course2','Course3')
)
SELECT *
FROM CTE AS c
PIVOT
(
MAX(Mark)
FOR CourseName IN ([Course1], [Course2], [Course3])
) u;
这会给你:
| firstname | lastname | Email | Course1 | Course2 | Course3 |
|-----------|----------|-------|---------|---------|---------|
| StudentA | test | test | 19 | 20 | 15 |
| StudentB | test | test | 16 | 17 | 20 |
| StudentC | test | test | 20 | 19 | 15 |
另请注意,您应该注意在锚查询中选择的列:
...
SELECT
k.name as firstname,
k.surname as lastname,
k.Email,
c.CourseName, dn.Mark
...
因为 PIVOT
table 运算符将按除您列出并用于透视的列之外的所有列进行分组:
MAX(CourseID)
FOR CourseName IN
因此在您的情况下,它将按 firstname, lastname, Email
.
我认为您可以使用比您更好的查询并使用 MAX(CASE ...)
来实现您的预期结果,如下所示:
SELECT k.name as firstname, k.surname as lastname, k.Email,
MAX(CASE WHEN c.CourseName = 'Course1' THEN 'Yes' ELSE 'No' END) As Course1,
MAX(CASE WHEN c.CourseName = 'Course2' THEN 'Yes' ELSE 'No' END) As Course2,
MAX(CASE WHEN c.CourseName = 'Course3' THEN 'Yes' ELSE 'No' END) As Course3
FROM Students k
JOIN StudentCourses dn ON dn.StudentID = k.StudentID
JOIN Courses c ON c.CourseID = dn.CourseID AND c.CourseName Like 'Course[1-3]'
GROUP BY k.name, k.surname, k.Email;