[英]MySql - Sql query or procedure to generate report by transposing rows into columns
这是第一次-我正在尝试做这样的事情-所以请多多包涵。 这是在MySql上。
我正在尝试生成一份报告,以查看哪些学生完成了哪些主题以及在什么日期完成。
这是我运行的当前查询
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
这将返回类似的结果
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
我要生成报告的方式是将主题名称作为列标题,并将其完成日期作为值
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
要注意的几件事是:
1)所有主题名称都将来自主题表-即使尚未由学生完成,该值也应显示为null
2)如果是学生abc@gmail.com-他已经研究了ABC主题两次-但报告应获得最新日期。
我想我必须编写一个存储过程来完成此任务。 就像首先从主题表中拉出所有主题名称,然后创建一个临时视图并填充它一样。
我会很感激您能提供的任何帮助。 非常感谢
我还没有测试过,我在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
当然,如果您的主题变化不是很规律,则可以使用:
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
并在每次添加新主题时更改查询(这是上述过程产生的查询)。
您可以使用动态生成的交叉表查询来执行此操作。 您想要结束的查询是这样的-
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;
因此,以您选择的服务器端语言,您将基于首先查询主题列表来动态构建字段列表。
您可以使用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.