我有3张桌子:
具有学生姓名的表_1(字段= StudentID,FirstName,LastName)
表_2,带有教师姓名(字段= TeacherID,FirstName,LastName,Initials *) (*“初始姓名”字段包含每个教师的姓名缩写:“ JD”代表“ John Doe”,“ FB”代表“ Fred Bloggs”,等等)
Table_3以及每个老师给每个学生的成绩(字段= StudentID,TeacherID,成绩)
我想生成一个查询,其中列出所有学生以及他们的成绩;像这样:
/elk
问题在于,FirstName和LastName之后的列应从Table_2的内容中“动态”生成(教师给出成绩)。换句话说,如果将一个新老师添加到该表中(例如Zack Zanny),则(在对所有学生进行评分之后)相同查询应产生如下内容:
server.basePath: "/elk"
我说清楚了吗?
我已经搜索了这个论坛和其他论坛,并尝试阅读mysql数据透视表,但是我必须做错了什么...任何指针将不胜感激。预先感谢。
答案 0 :(得分:0)
您不能编写一个SQL查询来根据找到的数据值动态扩展其列。选择列表中的列必须在准备查询时固定。
因此,在编写查询之前,您需要知道所有教师ID。一种方法是查询它们:
SELECT TeacherID FROM Table_2;
然后,基于该查询的结果,您的应用程序代码需要构建具有所需列数的数据透视SQL查询。换句话说,使用循环,为上一个查询返回的每个TeacherID的选择列表添加一列。
SELECT st.FirstName, st.LastName,
MAX(CASE TeacherId WHEN 'JD' THEN Grade END) AS `JD`,
MAX(CASE TeacherId WHEN 'FB' THEN Grade END) AS `FB`,
MAX(CASE TeacherId WHEN 'ZZ' THEN Grade END) AS `ZZ`
FROM Table_1 AS st
LEFT OUTER JOIN Table_3 AS gr ON st.StudentId = gr.StudentId
GROUP BY st.FirstName, st.LastName;
MAX()函数只是为了满足聚合查询的规则:select-list中的每一列都必须按GROUP BY子句中的名称进行命名,或者位于MAX()之类的聚合函数中。我假设每个学生每位老师都会有一个年级,所以我也可以使用MIN()甚至AVG()。
要进行数据透视查询,您必须在查询中显式地写入列,但是您可以通过首先发现存在哪个教师ID来自动完成该过程。
另一种选择是编写一个将学生加入成绩的查询,这意味着您的应用程序将为每个学生获取多行-每位老师一行。
SELECT st.FirstName, st.LastName, TeacherId, Grade
FROM Table_1 AS st
LEFT OUTER JOIN Table_3 AS gr ON st.StudentId = gr.StudentId;
然后,您将结果遍历到您的应用中,并根据需要以表格方式显示。
没有办法解决这个问题,要么编写一些应用程序代码以在准备查询之前构建查询,要么使用固定的查询,但是在获取原始数据后编写一些应用程序代码以制表结果数据。
无论哪种方式,代码都不是火箭科学。
答案 1 :(得分:0)
MySQL本身不支持动态数据透视,您必须使用动态sql:
This SO post给出了一个有效的示例,我为您的用例做了如下修改:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'MAX(IF(g.TeacherID = ''',
TeacherID,
''', g.grade, NULL)) AS ',
Initials
)
) INTO @sql
FROM table_2;
SET @sql = CONCAT('SELECT
s.firstname,
s.lastname,
', @sql, '
FROM
table_3 g
INNER JOIN table_1 s ON s.studentid = g.studentid
GROUP BY
s.studentid,
s.firstname,
s.lastname';
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;