SQL - 不同类别的列
我是SQL新手。我有用于不同的检查数据的数据库,例如:SQL - 不同类别的列
Student Test Grade
--------------------
St1 T1 A
St2 T1 B
St3 T1 B
St1 T2 B
St2 T2 B
St3 T2 A
St1 T3 A
St2 T3 C
St3 T3 B
然后,我想打印使用试验(T1,T2和T3)作为列的报告:
Student T1 T2 T3
----------------------
St1 A B A
St2 B B C
St3 B A B
我尝试了不同的东西,但我被卡在如何制作这样的打印输出。任何帮助表示赞赏!
用途:
SELECT t.student,
MAX(CASE WHEN t.test = 'T1' THEN t.grade END) AS T1,
MAX(CASE WHEN t.test = 'T2' THEN t.grade END) AS T2,
MAX(CASE WHEN t.test = 'T3' THEN t.grade END) AS T3
FROM TABLE t
GROUP BY t.student
嗨, 您太棒了!非常感谢!它完美解决了! 干杯! -Mike – 2010-08-31 17:40:11
@Mike Santos:不客气,欢迎来到SO。 – 2010-08-31 17:43:37
我相信,如果你打算把这个系统扩展到包括更多的信息,那么,你可以从返工你的数据库中受益,我将建立它像这样:
表名 =粗体
列名 =斜体
学生:
- SID(主键)
- 关于学生的其他信息
测试:
- TID(主键)
- 有关测试 其他信息
测试成绩
- GID(主键)
- TID(外键)
- SID(外键)
- 级
这个结构是基于一个叫做数据库正常化的想法(如果你是谷歌的话,你会得到很多信息)。我将在下面给你一个部分总结,但是如果你打算做很多SQL,你应该自己阅读:
首先要知道的是主键只是一个唯一的标识符,它是通常不是信息的一部分(但是,因为它是唯一的,所以每个数据必须具有不同的主键值),并且外键是从另一个表中的一行中引用一行中的行的方式,使用参考者的主键:例如这里的外键SID在每个年级引用单个学生,根据他们的主键SID。
例如学生有SID 1,他的所有测试在SID列中有1个。对于学生2,3,4等等同样如此。
规范化的基本思想是,所有的唯一数据只存储一次,然后在其他使用它的地方引用(如果你看看例子中键的结构,所有的学生信息都被存储在表中,然后参考他们的测试成绩,而不是在每个年级重复)。
要获取你想要的东西从这些表中我会用这个(它用PHP编写的):
$sql = 'SELECT * FROM Tests ORDER BY TID';
$tempresult = mysql_query($sql);
while($temprow = mysql_fetch_array($tempresult)){
echo $temprow['TID'];
}
$sql = 'SELECT * FROM Students';
$result = mysql_query($sql);
while($row = mysql_fetch_array($result)){
echo '\n'.$row['SID'];
$sql = 'SELECT * FROM Grades WHERE SID='.$row['SID'].' ORDER BY TID';
$result2 = mysql_query($sql);
while($row2 = mysql_fetch_array($result2)){
echo ' '.$rows['Grade'];
}
}
您可以在echo语句格式添加到这一点,并同时打印任你选择的额外信息加上。如果您有任何问题,请询问他们。
编辑:我已阅读其他人,并同意他们的方法在所有可能优于,我唯一不知道的是,数据透视表是否可以扩展以处理不同数量的测试,如果它可以(或者你不需要),那么我建议他们的方法,否则我觉得这可能在你的应用程序中有一席之地。
非常感谢您的详细信息!我真的很感激!谢谢! -Mike – 2010-09-02 09:41:07
尝试这个
SELECT Student, MAX(CASE WHEN Test = 'T1' THEN Grade END) AS T1,
MAX(CASE WHEN Test = 'T2' THEN Grade END) AS T2,
MAX(CASE WHEN Test = 'T3' THEN Grade END) AS T3 FROM tablename GROUP BY Student
使用,而不是 “表名” 你的表名。
有几种方法可以做到这一点,这两种方法(在纯SQL中而不是在生成SQL命令的代码中)都需要知道并修复的列数。最简单的实现将是:
SELECT eg.Student,
(SELECT Grade from ExamGrade eg1 WHERE eg1.Student = eg.Student AND Test = 'T1') AS T1
(SELECT Grade from ExamGrade eg2 WHERE eg2.Student = eg.Student AND Test = 'T2') AS T2
(SELECT Grade from ExamGrade eg3 WHERE eg3.Student = eg.Student AND Test = 'T3') AS T3
FROM ExamGrade eg
这将工作在几乎包括SQLite的任何环境中,它可以作出更多的优雅与标量值函数GetTest(),将采取学生和测试编号并返回等级。然而,无论如何,这既不是表现也不是封闭的改变;它将查询N次测试的平方N次,如果添加第四次测试,则该查询将不得不更改以将其包括在报告中。
如果Student和Test的组合是唯一的,而且您正在使用Pivot功能(显然SQLite没有)的数据库中工作,那么您可以使用Pivot查询以及任何聚合器(MAX /具有单个值的集合的MIN/AVG/SUM是该值)。以下作品在MSS2005中:
SELECT Student, T1, T2, T3
FROM (Select Student, Test, Grade FROM ExamGrade) As SourceQuery
PIVOT (MAX(Grade) FOR Test IN (T1, T2, T3)) AS PivotTable
这样会更高效,它更加优雅。列列表仍然不能动态确定AFAIK,但如果您从应用程序代码进行此查询或使用MS SQL Server中的sp_executesql内置存储过程从另一个存储过程生成查询,功能。
非常感谢您的信息! – 2010-09-02 09:41:38
使用“代码”按钮进行格式化可让您使用固定宽度的字体,帮助将这些表格排成一列并更具可读性 – ford 2010-08-31 17:29:08