MySQL查询问题,我无法得到它

时间:2010-06-23 20:15:56

标签: sql mysql pivot

我希望有人可以帮助我。我有一个记录导入工作的表。我需要一个查询,它将生成一个矩阵,其中包含垂直轴上的表名,水平轴上的导入日期,以及矩阵单元格中该日期为该表导入的记录总数。我不在乎是否必须创建一个临时表,但整个过程必须在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

3 个答案:

答案 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