繁体   English   中英

MySql-通过将行转置为列来生成报告的Sql查询或过程

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM