Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySql-通过将行转换为列来生成报告的Sql查询或过程_Mysql_Sql_Pivot_Pivot Table - Fatal编程技术网

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

MySql-通过将行转换为列来生成报告的Sql查询或过程,mysql,sql,pivot,pivot-table,Mysql,Sql,Pivot,Pivot Table,这是第一次-我正试图做这样的事情-所以请容忍我。 这是在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 选择u.email、t.

这是第一次-我正试图做这样的事情-所以请容忍我。 这是在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 选择u.email、t.topic\u name、tu.date\u创建为“完成日期” 来自主题用户tu 在tu.topic\u id=t.topic\u id上加入topic t 在tu.user\u id=u.user\u id上加入用户u 它将返回如下结果

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 电子邮件|主题|名称|完成日期 abc@gmail.com| ABC | 2012年1月3日 abc@gmail.com| DEF | 2012年2月3日 abc@gmail.com| ABC | 2012年8月3日 abc@gmail.com| GHI | 2012年8月3日 def@gmail.com| ABC | 2012年2月3日 def@gmail.com| XYZ | 2012年10月3日 我想要生成报告的方式是将主题名称作为列标题,并将完成报告的日期作为值

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 电子邮件| ABC | DEF | GHI | JKL | XYZ abc@gmail.com2012年8月3日| 2012年2月3日| 2012年8月3日|空|空 def@gmail.com2012年2月3日|空|空|空| 2012年10月3日 需要注意的几点是:

1) 所有主题名称都将来自主题表-即使学生尚未完成-该值应显示为空

2) 以防学生abc@gmail.com-他已经研究了两次ABC主题-但是报告应该是最新的日期

我想我必须编写一个存储过程来实现这一点。比如,首先从主题表中提取所有主题名称,然后创建临时视图并填充它

如果您能提供任何帮助,我将不胜感激。
非常感谢

您可以通过动态生成的交叉表查询来实现这一点。您希望最终得到的查询如下所示-

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_id而不是topic_名称,您可以稍微减少此查询的开销,这样您就可以删除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;

您可以通过动态生成的交叉表查询来实现这一点。您希望最终得到的查询如下所示-

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_id而不是topic_名称,您可以稍微减少此查询的开销,这样您就可以删除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;

我还没有测试过这个,我使用MySQL的经验也有限,但我希望下面的内容就是你想要的。它使用
GROUP\u CONCAT
函数动态创建
SELECT
语句,然后执行它(这是我不确定在MySQL中执行该语句的方式)

当然,如果您的主题没有经常更改,您可以使用:

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

并在每次添加新主题时更改查询(这是通过上述过程生成的查询)。

我还没有测试过这一点,而且我使用MySQL的经验有限,但我希望下面就是您想要的。它使用
GROUP\u CONCAT
函数动态创建
SELECT
语句,然后执行它(这是我不确定在MySQL中执行该语句的方式)

当然,如果您的主题没有经常更改,您可以使用:

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

并在每次添加新主题时更改查询(这是通过上述过程生成的查询)。

主题名称是否固定?它们可以在sql中硬编码吗?您是否保证每封电子邮件中每个主题名只完成一个日期?是的,主题名在创建课程时是固定的,主题表中填充了名称。根据需要添加新主题。不,正如我提到的,同一个学生可以多次学习同一主题,但报告应该显示最后的日期。如果你看abc@gmail.com学生-他已经完成了两次ABC主题,但报告显示了最后日期。谢谢主题名称确定了吗?它们可以在sql中硬编码吗?您是否保证每封电子邮件中每个主题名只完成一个日期?是的,主题名在创建课程时是固定的,主题表中填充了名称。根据需要添加新主题。不,正如我提到的,同一个学生可以多次学习同一主题,但报告应该显示最后的日期。如果你看abc@gmail.com学生-他已经完成了两次ABC主题,但报告显示了最后日期。谢谢你的解决方案。只要在MySQL>=5.0.13上,它就可以正常工作。谢谢-我喜欢主题不经常变化的解决方案-但是数据库有大约90多个主题,我必须添加所有这些案例。您的第一个动态创建的解决方案本来是理想的,但我无法实现这一点-我得到了一个错误-“您的SQL语法中有一个错误;请检查与您的MySQL服务器版本相对应的手册,以获得正确的语法,以便在第1行使用“to Banking,MAX”(当topic_id=3,然后tu.date_created END)作为T”我希望这是关于
主题的
的,其中有一个空格。我已编辑解决方案以解决此问题。如果不是这样,请在运行@SQL之前尝试选择它,这将向您显示已生成的查询,并应帮助您确定错误发生的位置。如果您将其更改为使用反勾号而不是单引号,则当文本中也有单引号时,它将起作用。@nnichol想法不错。我现在已经做出了改变。很好的解决方案。只要在MySQL>=5.0.13上,它就可以正常工作。谢谢-我喜欢主题不经常变化的解决方案-但是数据库有大约90多个主题,我会的