[英]MySql - Sql query or procedure to generate report by transposing rows into columns
This is the first time - I'm trying to do something like this - so please bear with me. 这是第一次-我正在尝试做这样的事情-所以请多多包涵。 This is on MySql.
这是在MySql上。
I am trying to generate a report to see which students have completed which topics and on which dates. 我正在尝试生成一份报告,以查看哪些学生完成了哪些主题以及在什么日期完成。
This is the current query that I run 这是我运行的当前查询
select u.email,t.topic_name,tu.date_created as 'date completed' from topic_user tu join topic t ON tu.topic_id = t.topic_id join user u ON tu.user_id = u.user_id
which will return results like 这将返回类似的结果
email | topic_name | date completed abc@gmail.com | ABC | 03/01/2012 abc@gmail.com | DEF | 03/02/2012 abc@gmail.com | ABC | 03/08/2012 abc@gmail.com | GHI | 03/08/2012 def@gmail.com | ABC | 03/02/2012 def@gmail.com | XYZ | 03/10/2012
The way I want to generate the report is have the topic names as column headers and the date they completed it as values 我要生成报告的方式是将主题名称作为列标题,并将其完成日期作为值
email | ABC | DEF | GHI | JKL | XYZ abc@gmail.com | 03/08/2012 | 03/02/2012 | 03/08/2012 | null | null def@gmail.com | 03/02/2012 | null | null | null | 03/10/2012
Few things to note are: 要注意的几件事是:
1) All the topic names would come from the topic table - even if they have not been completed by the students - the value should appear as null 1)所有主题名称都将来自主题表-即使尚未由学生完成,该值也应显示为null
2) Incase of student abc@gmail.com - he has studied the topic ABC twice - but the report should get the latest date. 2)如果是学生abc@gmail.com-他已经研究了ABC主题两次-但报告应获得最新日期。
I guess I have to write a stored procedure to accomplish this. 我想我必须编写一个存储过程来完成此任务。 Like maybe first pull all the topic names from the topic table and then create a temp view and populate it.
就像首先从主题表中拉出所有主题名称,然后创建一个临时视图并填充它一样。
I would appreciate any help you can provide. 我会很感激您能提供的任何帮助。 Thanks much
非常感谢
I've not tested this, and my experience with MySQL is limited but I hope the below is what you are after. 我还没有测试过,我在MySQL方面的经验有限,但是我希望下面是您所追求的。 It dynamically creates the
SELECT
statement using the GROUP_CONCAT
function, then executes it (This is the bit I am not certain of the way to do it in MySQL). 它使用
GROUP_CONCAT
函数动态创建SELECT
语句,然后执行它(这是我不确定在MySQL中执行它的方式)。
SET @SQL = (
SELECT CONCAT('SELECT Email,', GROUP_CONCAT(SelectText), ' FROM Topic_User tu INNER JOIN Users u ON u.User_ID = tu.User_ID GROUP BY Email')
FROM ( SELECT CONCAT(' MAX(CASE WHEN Topic_ID = ', Topic_ID, ' THEN tu.Date_Created END) AS `', Topic_Name, '`') AS SelectText
FROM Topic
) AS d);
PREPARE stmt FROM @SQL;
EXECUTE stmt
Of course if your topics are not changing very regularly you could just use: 当然,如果您的主题变化不是很规律,则可以使用:
SELECT Email,
MAX(CASE WHEN Topic_ID = 1 THEN tu.Date_Created END) AS ABC,
MAX(CASE WHEN Topic_ID = 2 THEN tu.Date_Created END) AS DEF,
MAX(CASE WHEN Topic_ID = 3 THEN tu.Date_Created END) AS GHI,
MAX(CASE WHEN Topic_ID = 4 THEN tu.Date_Created END) AS JKL,
MAX(CASE WHEN Topic_ID = 5 THEN tu.Date_Created END) AS XYZ
FROM Topic_User tu
INNER JOIN users u
ON u.User_ID = tu.User_ID
GROUP BY Email
and alter the query each time a new topic is added (This is the query produced by the process above). 并在每次添加新主题时更改查询(这是上述过程产生的查询)。
You could do this with a dynamically generated crosstab query. 您可以使用动态生成的交叉表查询来执行此操作。 The query you want to end up with is something like this -
您想要结束的查询是这样的-
SELECT
u.email,
MAX(IF(t.topic_name = 'ABC', tu.date_created, NULL)) AS 'ABC',
MAX(IF(t.topic_name = 'DEF', tu.date_created, NULL)) AS 'DEF',
etc
FROM topic_user tu
INNER JOIN topic t
ON tu.topic_id = t.topic_id
INNER JOIN user u
ON tu.user_id = u.user_id
GROUP BY u.user_id;
So, in your server side language of choice you would dynamically build your field list based on first querying for a list of topics. 因此,以您选择的服务器端语言,您将基于首先查询主题列表来动态构建字段列表。
You could slightly reduce the overhead of this query by using the topic_ids instead of the topic_names so that you can drop the join to the topics table - 您可以使用topic_ids代替topic_names来稍微减少此查询的开销,从而可以将联接删除到topics表-
SELECT
u.email,
MAX(IF(tu.topic_id = 1, tu.date_created, NULL)) AS 'ABC',
MAX(IF(tu.topic_id = 2, tu.date_created, NULL)) AS 'DEF',
etc
FROM topic_user tu
INNER JOIN user u
ON tu.user_id = u.user_id
GROUP BY u.user_id;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.