SQL-不同类别的列
我是SQL新手。我有一个包含不同考试数据的数据库,例如:SQL-不同类别的列,sql,sqlite,pivot,Sql,Sqlite,Pivot,我是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 --
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
不久前我问了一个类似的问题。您需要类似于透视表的东西,但在SQLite中不可用(据我所知)。我相信,如果您打算扩展此系统以包含更多信息,您可以从修改数据库中获益,我会这样构建它: 表名=粗体 列名=斜体 学生:
- SID(主键)
- 关于该学生的其他信息
- TID(主键)
- 关于测试的其他信息
- GID(主键)
- 工业贸易署(外键)
- SID(外键)
- 等级
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
使用表名而不是“tablename”。有几种方法可以做到这一点,这两种方法(在纯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平方次表,如果添加第4个测试,则必须更改此查询以将其包含在报告中
如果Student和Test的组合是唯一的,并且您在一个具有Pivot功能的数据库中工作(显然SQLite没有),那么您可以将Pivot查询用于几乎任何聚合器(具有单个值的集合的MAX/MIN/AVG/SUM就是该值)。2005年的工作如下:
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
这将更具性能,也更优雅。列列表仍然无法动态确定,但如果您是从应用程序代码进行此查询,则生成列列表非常简单,或者使用MS SQL Server中的sp_executesql内置存储过程从另一个存储过程或函数生成查询。我想对@OMG_Ponies的答案添加一些解释,因为它可能对SQL无超级用户(如我自己)有用 让我们创建一个示例表并添加虚拟数据:
CREATE TABLE t (
t_ID integer primary key autoincrement not null,
student integer,
test text,
grade text
);
INSERT INTO t
(student, test, grade)
VALUES
('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');
因此,我们有以下几点:
t_ID student test grade
-------------------------
1 St1 T1 A
2 St2 T1 B
3 St3 T1 B
4 St1 T2 B
5 St2 T2 B
6 St3 T2 A
7 St1 T3 A
8 St2 T3 C
9 St3 T3 B
使用语句case时。。。然后。。。结束
可以获得所需的列
SELECT
t_ID,
student,
(case when t.test = 'T1' then t.grade end) as T1,
(case when t.test = 'T2' then t.grade end) as T2,
(case when t.test = 'T3' then t.grade end) as T3
FROM t
order by student
结果
t_ID student T1 T2 T3
----------------------------------
1 St1 A NULL NULL
4 St1 NULL B NULL
7 St1 NULL NULL A
2 St2 B NULL NULL
5 St2 NULL B NULL
8 St2 NULL NULL C
3 St3 B NULL NULL
6 St3 NULL A NULL
9 St3 NULL NULL B
t_ID student T1 T2 T3
-----------------------------
7 St1 A B A
8 St2 B B C
9 St3 B A B
然而,我们发现有必要按字段“学生”对结果进行分组。分组时,我们必须指定一个聚合函数,以指定在多行具有相同值“student”的情况下保留哪个值。在本例中,我们使用“max”函数来丢弃空值
SELECT
t_ID,
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 t
GROUP BY student
ORDER BY student
结果
t_ID student T1 T2 T3
----------------------------------
1 St1 A NULL NULL
4 St1 NULL B NULL
7 St1 NULL NULL A
2 St2 B NULL NULL
5 St2 NULL B NULL
8 St2 NULL NULL C
3 St3 B NULL NULL
6 St3 NULL A NULL
9 St3 NULL NULL B
t_ID student T1 T2 T3
-----------------------------
7 St1 A B A
8 St2 B B C
9 St3 B A B
最后一点。由于我们还没有按t_ID分组,也没有为其指定聚合函数,因此您应该假设每行的t_ID的值是每组的随机值。小心点 “代码”按钮的格式设置将允许您使用固定宽度的字体,帮助这些表格排列整齐,更具可读性嗨,您太棒了!非常感谢你!结果很完美!干杯-MikeThank非常感谢您提供的详细信息!我真的很感激!谢谢大家!-迈克