2012-05-28 37 views
1

我必须生成每天和每小时完成的任务量报告。这样,报告将看起来像一个网格。选择日/小时数据

我希望横轴的月份(从1到31)和纵向的小时(从8:00到18:00)。

如何在PostgreSQL中使用SQL从数据库中选择这种数据?

+0

假设我有一个名为“任务”同场ID,date_time_of_task表,fk_who_did_it –

+0

是否已进行了在SQL之前的任何'SELECT'陈述?如果你知道如何安排电网,那么你已经到了一半。试着理解用来构造它的逻辑。我建议提出一些广泛的查询并发布您的尝试,然后其他人可以来帮助您优化查询以生成报告。你必须至少付出一些努力! – Zairja

+0

我知道一点SQL ......问题是如何分隔每小时的结果?我以前从未这样做=/ –

回答

1

您正在查找的查询是SQL聚合查询。它看起来有点复杂,但结构非常简单。

select extract(hour from date_time_of_task) as thehour, 
     sum(case when extract(day from date_time_of_task) = 1 then 1 else 0 end) as day_01, 
     sum(case when extract(day from date_time_of_task) = 2 then 1 else 0 end) as day_02, 
     sum(case when extract(day from date_time_of_task) = 3 then 1 else 0 end) as day_03, 
     sum(case when extract(day from date_time_of_task) = 4 then 1 else 0 end) as day_04, 
     ... up to day 31 
group by extract(hour from date_time_of_task) 
order by 1 

这只是按一天中的小时分组。然后它为每个月的每一天手动调整数据。 “总和”计算同时满足两个条件的行数 - 行的小时数和列的日期。

+0

好,我测试了两种方法并获得了预期的结果。谢谢! =) –

1

的关键元素,以一个很好的解决方案是generate_series()date_part(),一个CTEGROUP BYcount(*)LEFT JOIN最后:从附加模块tablefunccrosstab()函数(1个参数)。要安装它,运行一次每个数据库:

CREATE EXTENSION tablefunc; 

查询:

SELECT * 
FROM crosstab($x$ 

WITH x AS (
    SELECT date_part('day', date_time_of_task)::int AS d 
      ,date_part('hour', date_time_of_task)::int AS h 
      ,count(*)::int AS ct 
    FROM tasks 
    GROUP BY 1,2 
    ) 
SELECT d, h, ct 
FROM (SELECT generate_series(1,31) AS d, generate_series(0,23) AS h) t 
LEFT JOIN x USING (d,h) 
ORDER BY 1,2 

$x$) 
AS orders(
day int 
,h8 int, h9 int, h10 int, h11 int, h12 int, h13 int, h14 int, h15 int 
,h16 int, h17 int, h18 int); 

主要生产天数和小时的矩阵中每个字段的任务数像你描述。

顺便说一句:我用这个辅助。函数生成的目标定义列表:

SELECT 'day int, ' || string_agg (x, ', ') 
FROM (SELECT ('h' || generate_series(8,18) || ' int') AS x) a