选择每日/每小时数据

时间:2012-05-28 16:29:05

标签: sql postgresql datetime aggregate-functions crosstab

我必须生成每天和每小时完成的任务量的报告。这样,报告看起来就像一个网格。

我希望水平轴上的月份(从1到31),以及垂直的小时(从8:00到18:00)。

如何在PostgreSQL中使用SQL从数据库中选择此类数据?

2 个答案:

答案 0 :(得分:2)

您要查找的查询是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

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

答案 1 :(得分:1)

优雅解决方案的关键要素是generate_series()date_part()CTEGROUP BYcount(*)LEFT JOIN,最后:附加模块crosstab()中的tablefunc函数(带有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);

生成一个天数和小时矩阵,其中包含您描述的每个字段中的任务数。

BTW:我用过这个辅助。用于生成目标定义列表的函数:

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