4

我需要在一组记录中获取一天中最常见的时刻(黎明、早晨、傍晚、夜晚)。我正在尝试使用 CASE-WHEN 将结果分组,但我无法比较日期和整数。我试试这个:

SELECT done_at,
  case done_at
  when date_trunc('hour', done_at) > 0 and date_trunc('hour', done_at) <= 7 then
    'dawn'
  when dayhour > 7 and dayhour <= 12 then
    'morning'
  when dayhour > 12 and dayhour <= 20 then
    'evening'
  when dayhour > 20 and dayhour <= 00 then
    'night'
  end
FROM iterations;

但是得到这个错误:

ERROR:  operator does not exist: timestamp without time zone > integer
LINE 3:       when date_trunc('hour', done_at) > 0 and date_trunc('h...

我也尝试将类型转换为整数,但我得到了这个:

ERROR:  cannot cast type timestamp without time zone to integer
LINE 3:       when date_trunc('hour', done_at)::integer > 0 and date...

问题是它done_at确实有一个时区。从 Rails 控制台:

?> Iteration.first.done_at
=> Fri, 23 Sep 2011 02:00:00 CEST +02:00

而现在我一无所知。如何获得一天中的时刻?

4

2 回答 2

3

查询可能如下所示:

SELECT CASE 
        WHEN h >= 0  AND h <= 7  THEN 'dawn'  -- including 0 !
        WHEN h >  7  AND h <= 12 THEN 'morning'
        WHEN h > 12  AND h <= 20 THEN 'evening'
        WHEN h > 20              THEN 'night'
       END AS moment
     , count(*) AS cnt
FROM  (
    SELECT extract(hour from done_at) AS h
    FROM   iterations
    ) x
GROUP  BY 1
ORDER  BY count(*) DESC
LIMIT  1;

要点:

  • @lanzz 是对的extract()
  • 使用子查询计算一天中的小时以大大简化代码。
  • GROUP BY, count(),ORDER BY并且LIMIT可以发生在一个查询级别。
  • 结果是所要求的一天中最常见的时刻

done_at显然是类型timestamptz。因此提取的小时数取决于当前会话的时区设置。要删除此依赖项,您可能需要明确定义要使用的时区:

extract(hour FROM done_at AT TIME ZONE 'Europe/Vienna') AS h

看:

于 2011-11-07T21:49:23.087 回答
1

你想要extract(hour from done_at)而不是date_trunc('hour', done_at)

于 2011-11-07T21:24:50.960 回答