Sql 使学生的课程位于同一行的查询
我需要一个查询,将得到谁得到课程1,课程2和课程3的学生。我可以这样查询:Sql 使学生的课程位于同一行的查询,sql,sql-server,tsql,pivot,Sql,Sql Server,Tsql,Pivot,我需要一个查询,将得到谁得到课程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','C
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。一个学生不能有多行,一行写下课程名称,如果学生得到了该课程
事实上,我可以想象如何编写该查询(使用subselect),想知道更好的替代方法。您可以使用
PIVOT
表操作符来执行此操作,类似于:
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;
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;
请注意,由于您没有其他列显示在每个学生的每一列课程下,如果学生没有此课程,此查询将显示每个课程名称的
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…
来实现您的预期结果,如下所示:
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;
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;
使用PIVOT/UNPIVOT运算符,您可以仅使用一个学生和课程列拉动行,并使用该运算符转换数据或抛出一些示例数据(无图像)a并输出所需结果假设您只有3门课程我已硬编码案例,否则需要更改查询
选择k.name作为firstname,k.姓氏作为lastname,k.电子邮件,当dn.CourseName='Course1'然后'Course1'其他'-'作为Course1结束时,当dn.CourseName='Course2'然后'Course2'其他'-'作为Course2结束时,当dn.CourseName='Course3'然后'Course3'其他'-'作为Course3结束时,从Students k加入StudentCourses dn ON dn.StudentID=k.StudentID加入CourseId作为ci ON dn.CourseId=ci.id
您希望在coursename下为每行显示什么?我可以写课程名称或是/否。无所谓。