-2

我正在尝试对 postgresql 9.1 表进行查询,其中两个相关列是:

occurred - timestamp with timezone
computer - varchar

假设该表涵盖了从午夜到午夜的 24 小时时段,并且我需要获得一个 24 长度的列表,其中每个元素是台计算机在一天中的那个小时所拥有的行数。我将获得该WHERE子句的计算机名称。

到目前为止,这是我的 sql:

select extract(hour from occurred) as hr, count(where computer = "computername") 
    from tablename group by extract(hour from occurred) order by 1
4

2 回答 2

2

您的查询是一个很好的起点。您需要旋转这些值。这是一种方法:

select computer,
       sum(case when hr = 1 then cnt else 0 end) as hr01,
       sum(case when hr = 2 then cnt else 0 end) as hr02,
       sum(case when hr = 3 then cnt else 0 end) as hr03,
       ...
       sum(case when hr = 24 then cnt else 0 end) as hr24
from (select computer, extract(hour from occurred) as hr, count(*) as cnt 
      from tablename
      group by computer extract(hour from occurred
     ) t
group by computer

(实际上,我忘记了小时是从 0 到 23 还是从 1 到 24。)

这会为每台计算机创建一个表,并在单独的列中按小时计数。

于 2012-08-03T14:57:00.437 回答
2

您将需要收紧此查询,以便一次只计算一天的数据,而不是生成计算机在全天 05:00 和 06:00 之间处于活动状态的次数的计数当它被记录为活动时。当计算机根本没有被记录为活动时,您还需要担心在几个小时内生成零计数。但是,我们可以将您的 SQL 修改为可能或多或少有用的东西:

SELECT EXTRACT(HOUR FROM occurred) AS hr, COUNT(*) AS count
  FROM tablename
 WHERE computer = 'computername'  -- corrected (" ⟶ ')
 GROUP BY EXTRACT(HOUR FROM occurred)
 ORDER BY 1

从语法上讲,这是正确的(我认为)。

这是定义特定日期的许多可能方法之一。您可能需要指定时区以获得更可靠的数据。

SELECT EXTRACT(HOUR FROM occurred) AS hr, COUNT(*) AS count
  FROM tablename
 WHERE computer = 'computername'  -- corrected (" ⟶ ')
   AND occurred >= TIMESTAMP '2012-08-02 00:00:00'
   AND occurred <  TIMESTAMP '2012-08-03 00:00:00'
 GROUP BY EXTRACT(HOUR FROM occurred)
 ORDER BY 1

即使在其中一些小时内没有计算机活动,生成所有 24 小时的数据也更加困难。您会以某种方式创建一个 24 小时列表(有多种可能的方法;我不确定哪种方法在 PostgreSQL 中最合适),然后将其与计算机活动记录的投影相结合:

SELECT hh, COUNT(*)
  FROM hours_00_to_23 AS h
  LEFT JOIN
       (SELECT EXTRACT(HOUR FROM occurred) AS hh
          FROM tablename
         WHERE computer = 'computername'  -- corrected (" ⟶ ')
       ) AS a
    ON a.hh = h.hh
 GROUP BY hh
 ORDER BY hh

您可以结合条件来获取特定日期的数据等。

警告:没有 DBMS 被试图在这个答案中运行任何假定的 SQL 所困扰!

我不知道如何解决第三个问题,第二行不存在关系“hours_00_to_23”。

您需要创建一个(临时?)表,其中包含一个hh适当类型的列(这本身就是一个有趣的问题 - 正确的类型是什么)填充值 0 到 23。一个可能令人讨厌的蛮力解决方案(有争议的类型)是:

CREATE TABLE hours_00_to_23(hh INTEGER NOT NULL PRIMARY KEY);
INSERT INTO hours_00_to_23 VALUES(0);
INSERT INTO hours_00_to_23 VALUES(1);
...
INSERT INTO hours_00_to_23 VALUES(23);

可能还有其他方法可以达到相同的效果。

于 2012-08-03T15:29:33.117 回答