SQL:重复实例,放入一行

Posted

技术标签:

【中文标题】SQL:重复实例,放入一行【英文标题】:SQL: Duplicate instances, into one row 【发布时间】:2016-09-05 03:32:24 【问题描述】:

我在我们的数据库上运行了一个基本的 SQL 查询,它会返回学生数据。一个学生可以在不同的课程上有多个实例,例如:

StudentID        StudentFullName        Course        StartDate
123456           J.Bloggs               BA            01/11/2012
123456           J.Bloggs               MBA           01/07/2015
234567           R.Head                 BA            09/04/2014

我要做的是合并重复的学生记录(可能基于 ID 或姓名)并将课程数据放入同一行,使最终结果看起来像这样:

StudentID        StudentFullName        Course1       StartDate1       Course2    StartDate2
123456           J.Bloggs               BA            01/11/2012       MBA        01/07/2015
234567           R.Head                 BA            09/04/2014

可能存在学生有超过 2 门课程的情况,因此代码需要灵活以允许这样做(Course3、Course 4 等)。

我还会考虑运行查询以查找在特定时间段 (>='2014/08/01') 后开始“Course1”的学生。

到目前为止,我只能通过运行原始代码然后在电子表格中进行编辑来手动重新创建所需的结果(耗时)。

【问题讨论】:

阅读tutorialspoint.com/sql/first-normal-form.htm 并规范您的数据库。 我以前读过有关 pivot 的文章,但不知道从哪里开始。有什么建议吗? 【参考方案1】:

透视多个列的最简单方法之一是使用聚合大小写表达式。

您必须使用 ROW_NUMBER 来确定课程是 course1、course2 等。然后只需在案例表达式中使用生成的 ROW_NUMBER。

SELECT  [StudentID],
        [StudentFullName],
        MAX(CASE WHEN Rn = 1 THEN [Course] END) AS Course1,
        MAX(CASE WHEN Rn = 1 THEN [StartDate] END) AS StartDate1,
        MAX(CASE WHEN Rn = 2 THEN [Course] END) AS Course2,
        MAX(CASE WHEN Rn = 2 THEN [StartDate] END) AS StartDate2
FROM    (
            SELECT  *, ROW_NUMBER() OVER (PARTITION BY [StudentID] ORDER BY [StartDate] DESC) Rn
            FROM    Table1
        ) t
GROUP BY [StudentID],
        [StudentFullName]

这些查询也可以通过构建 MAX(CASE) 部分来动态完成。

【讨论】:

【参考方案2】:

您在任何其他编程语言中使用 SQL 吗?如果是这样,您可以使用 if 语句添加新列,但动态添加或删除列会导致异常。 我认为创建一个单独的表格会给你带来最好的结果。那么你应该有三个表:

学生数据(StudentID、StudentFullName)

课程(CourseID、CourseName)

StudentCourses(CourseID、StudentID、StartDate)

这是一个优化的方案。

希望我能帮上忙,如果没有,请随时提出更多问题。

编辑:这可能需要更多的努力,因为课程是分开存储的,但它应该是最快和最节省存储空间的解决方案。 如评论中所述:这是该方案的规范化。

也许更容易的是有两个表的方案: 学生数据(学生 ID,学生全名) StudentCourses(CourseName,StudentID, StartDate)

【讨论】:

【参考方案3】:

特别是由于您的课程数量是灵活的,您将无法将其放在一张桌子上。即SQL Server不支持“灵活列表”这一概念。

相反,您的问题可能是normalization to the 2NF form 之一。

考虑创建一个包含 Student ID、Course、Start Date 列的新表 StudentCourses。 像 J.Bloggs 这样的学生将有两个条目,而 R.Head 将只有一个条目。 您当前的学生表仅保留学生信息,例如姓名、出生日期、学分等。

然后,根据您的需要,您始终可以构建获取该信息的查询或视图。

【讨论】:

以上是关于SQL:重复实例,放入一行的主要内容,如果未能解决你的问题,请参考以下文章

SQL中删除重复的行(重复数据),只保留一行 转

sql限制无法显示第一行[重复]

SQL如何选择所有重复id的行,但不是每行的第一行?

SQL从重复行中只选择一行

在 SQL 数据库网页中删除一行 [重复]

用于获取重复记录并在 Gridview 中显示为一行的 SQL 查询