我希望有人可以帮助我。我有一个记录导入工作的表。我需要一个查询,它将生成一个矩阵,其中包含垂直轴上的表名,水平轴上的导入日期,以及矩阵单元格中该日期为该表导入的记录总数。我不在乎是否必须创建一个临时表,但整个过程必须在MySQL中完成。
以下是我们的事件日志表的简化示例。它不仅有更多的fieds,而且我们导入更多的表。因此,解决方案应该考虑查询表名。您会注意到,数据可以每天多次导入表格,如记录5和6中所示。
id table_name import_date num_recs
----+-----------+--------------------+-------
0 customer 2010-06-20 00:00:00 10
1 order 2010-06-20 00:00:00 15
2 customer 2010-06-21 00:00:00 5
3 order 2010-06-21 00:00:00 6
4 customer 2010-06-22 00:00:00 1
5 order 2010-06-22 00:00:00 6
6 order 2010-06-22 00:00:00 1
我们正在寻找这样的结果。它不一定是准确的
table_name 06-20 06-21 06-22
------------+-----+-----+------
customer | 10 | 5 | 1
order | 15 | 6 | 7
答案 0 :(得分:3)
表格输出怎么样:
table_name date imports
------------+-------+--------
customer | 06-20 | 10
customer | 06-21 | 5
order | 06-20 | 15
order | 06-21 | 6
通过这种方式,您可以使用简单的GROUP BY
:
SELECT table_name, DATE(import_date) AS date, SUM(*) AS imports
FROM yourTable
GROUP BY table_name, date;
否则,您的查询将真的讨厌。
答案 1 :(得分:2)
MySQL无法进行数据透视查询,但您可以在两个查询中执行此操作,使用第一个查询的结果作为下一个查询的SQL:
SELECT 'SELECT table_name'
UNION
SELECT CONCAT(', SUM(IF(import_date = "',import_date,'", num_recs,0)) AS "',DATE_FORMAT(import_date, "%m-%d"),'"')
FROM event_log
GROUP BY import_date
UNION
SELECT 'FROM event_log GROUP BY table_name'
然后执行该查询的输出以获得最终结果,例如为你的例子,你会得到:
SELECT table_name
, SUM(IF(import_date = "2010-06-20", num_recs,0)) AS "06-20"
, SUM(IF(import_date = "2010-06-21", num_recs,0)) AS "06-21"
, SUM(IF(import_date = "2010-06-22", num_recs,0)) AS "06-22"
FROM event_log GROUP BY table_name
您可以编写存储过程来连接,准备,然后执行第一个查询的结果,或者,如果这一切都是从shell脚本运行的,则可以捕获第一个查询的结果,然后输入结果回到了mysql。
答案 2 :(得分:0)
我认为Ben S走在正确的轨道上。我想提供我能在这里提供的服务,以防有人知道。 Original source
这是一种获取两个任意日期并将它们拆分成时间块的方法,然后对每个块中的其他数据执行一些聚合功能。在您的情况下,该块可能应该是一天,开始日期可能是当天前30天,结束日期可能是当天。可以返回每个块以及一些感兴趣的聚合度量。在您的情况下,这可能是SUM('imports')
SELECT t1.table_name AS table_name, t1.imports AS imports FROM (SELECT SUM(`imports`) AS imports, CEIL( (UNIX_TIMESTAMP('<now>') - UNIX_TIMESTAMP(`import_date`))/ (<one day in ?seconds, i think?>) ) AS RANGE FROM `<your table>` WHERE `import_date` BETWEEN '<now minus 30 days>' AND '<now>' GROUP BY RANGE ORDER BY RANGE DESC) AS t1;
这可能根本没有帮助,但如果它确实那么好。可以轻松修改它以将每个范围的开始日期作为日期列返回。为了清楚起见,这与Ben S的解决方案提供的完全相同,但如果您的所有日期都不是00:00:00,那么它将起作用,而这会导致他的日期列上的GROUP BY
失败
要查看返回的内容,请参阅Ben S的回答并精神上删除日期列。正如我所说,该列可以很容易地添加回此查询。 FWIW,我已经在超过400万行的表上使用了这种方法,它仍然以&lt; 1秒,这对我的目的来说足够好了。
Hamy