查询将学生的课程安排在同一行

时间:2015-10-15 08:48:50

标签: sql sql-server tsql pivot

我需要一个查询来获得获得Course1,Course2和Course3的学生。我可以这样查询:

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。如果学生获得该课程,则学生没有多行,一行和写课程名称。

事实上,我可以想象如何编写该查询(使用子选择),想知道更好的替代方案。

2 个答案:

答案 0 :(得分:3)

您可以使用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;

请注意:由于您没有为每位学生在每列课程下显示其他列,因此此查询将为每个课程名称显示CourseID值,{ {1}}如果学生没有这门课程。您应该选择显示更合适的列,例如标记:

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

因此,在您的情况下,它将按MAX(CourseID) FOR CourseName IN 分组。

答案 1 :(得分:1)

我认为您可以使用比您更好的查询,并使用firstname, lastname, Email来实现您的预​​期结果:

MAX(CASE ...)