【问题标题】:SQL Multiple joins - must be an easier waySQL 多连接 - 必须是更简单的方法
【发布时间】:2015-01-05 22:49:34
【问题描述】:

我有一个名为 Grades 的表,我们将学生的成绩存储到其中,他们每年和参加考试的学期都在其中。然后我们将其显示为 NCL、GCSE 或 Point 成绩。为了找到 NCL/GCSE 等效成绩,我们在另一个表上进行查找,该表将点映射到正确的 GCSE/NCL 等效成绩。

但是,这意味着我的查询有许多连接来为我们的成绩表返回匹配的 GCSE/NCL 成绩,我相信一定有更简单的方法

我的代码如下:

SELECT        
    Grades.GradeID, Grades.PupilID, Grades.GradeType, Grades.KeyStage2, Grades.Y7T1, 
    Grades.Y7T2, Grades.Y7T3, Grades.Y8T1, Grades.Y8T2, Grades.Y8T3, Grades.Y9T1, Grades.Y9T2, 
    Grades.Y9T3, Grades.Y10T1, Grades.Y10T2, Grades.Y10T3, Grades.Y11T1, Grades.Y11T2, 
    Grades.Y11T3, GradesToPoints.GCSEGrade AS KS2, 
    GradesToPoints_Y7T2.GCSEGrade AS [Year7 Term2], 
    GradesToPoints_Y7T3.GCSEGrade AS [Year7 Term3], 
    GradesToPoints_Y7T1.GCSEGrade AS [Year7 Term1], 
    GradesToPoints_Y8T1.GCSEGrade AS [Year8 Term1], 
    GradesToPoints_Y8T2.GCSEGrade AS [Year8 Term2], 
    GradesToPoints_Y8T3.GCSEGrade AS [Year8 Term3], 
    GradesToPoints_Y9T1.GCSEGrade AS [Year9 Term1], 
    GradesToPoints_Y9T2.GCSEGrade AS [Year9 Term2], 
    GradesToPoints_Y9T3.GCSEGrade AS [Year9 Term3], 
    GradesToPoints_Y10T1.GCSEGrade AS [Year10 Term1], 
    GradesToPoints_Y10T2.GCSEGrade AS [Year10 Term2], 
    GradesToPoints_Y10T3.GCSEGrade AS [Year10 Term3], 
    GradesToPoints_Y11T1.GCSEGrade AS [Year11 Term1], 
    GradesToPoints_Y11T2.GCSEGrade AS [Year11 Term2], 
    GradesToPoints_Y11T3.GCSEGrade AS [Year11 Term3], Grades.Subject
FROM            
    Grades 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y11T3 ON Grades.Y11T3 = GradesToPoints_Y11T3.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y11T2 ON Grades.Y11T2 = GradesToPoints_Y11T2.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y11T1 ON Grades.Y11T1 = GradesToPoints_Y11T1.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y10T3 ON Grades.Y10T3 = GradesToPoints_Y10T3.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y10T2 ON Grades.Y10T2 = GradesToPoints_Y10T2.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y10T1 ON Grades.Y10T1 = GradesToPoints_Y10T1.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y9T3 ON Grades.Y9T3 = GradesToPoints_Y9T3.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y9T2 ON Grades.Y9T2 = GradesToPoints_Y9T2.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y8T3 ON Grades.Y8T3 = GradesToPoints_Y8T3.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y8T2 ON Grades.Y8T2 = GradesToPoints_Y8T2.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y8T1 ON Grades.Y8T1 = GradesToPoints_Y8T1.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y7T3 ON Grades.Y7T3 = GradesToPoints_Y7T3.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y7T2 ON Grades.Y7T2 = GradesToPoints_Y7T2.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y7T1 ON Grades.Y7T1 = GradesToPoints_Y7T1.Points 
LEFT OUTER JOIN
    GradesToPoints ON Grades.KeyStage2 = GradesToPoints.Points 
LEFT OUTER JOIN
    GradesToPoints AS GradesToPoints_Y9T1 ON Grades.Y9T1 = GradesToPoints_Y9T1.Points
WHERE        
    (Grades.PupilID = @PupilID) AND (Grades.Subject = @Subject)

【问题讨论】:

  • 对我来说这看起来像是一个数据库设计问题;您不能将年份和学期与成绩一起作为列存储在一个表中,而不是拥有这么多表吗?如果你真的有那么多学生,你仍然可以使用一张表并按年分区。
  • 如果您显示示例数据和所需的输出,肯定会有人帮助您将其标准化。
  • 我需要将 GradesToPoints 表保留为单独的表,因为 GCSE/NCL 成绩可以更改为等效分数。积分将始终保持不变。例如,50 分可能在一年等于 A+,或在下一年等于 A-。
  • unpivot 然后join 然后pivot 可能会有所帮助。
  • Shannon,我想你可能有答案,尽管我从未使用过 pivot 或 unpivot。请你提供一个我如何使用它的例子

标签: sql sql-server database select join


【解决方案1】:

您的问题是您的数据模型未正确规范化。

您的成绩表似乎有每个学生的 1 条记录,每个成绩有一列。

相反,您的成绩表应该有每个成绩的 1 条记录,并有一个额外的列来表示成绩的类型、Y7T1、Y7T2 等。这也增加了灵活性:您在添加时不必更改数据库结构或删除某些成绩。

【讨论】:

  • 我同意,以这种方式规范化数据库会更好。尽管我们现在在数据库中存储了大量数据,所以并不想更改数据库,只需以更好的方式查询数据即可
  • 这称为技术债务。我的建议是看一看并理解这个术语。
猜你喜欢
  • 2014-09-30
  • 2014-06-02
  • 2014-10-14
  • 2021-10-20
  • 1970-01-01
  • 1970-01-01
  • 2017-02-07
  • 2015-12-29
  • 1970-01-01
相关资源
最近更新 更多