1

我有一个基于 CTE 的查询,我在其中检索两个给定时间戳之间的用户请求总量,并显示两个日期之间每小时发出的请求数。我的查询工作如下:

1)获取开始和结束日期时间(假设 07-13-2011 10:21:09 和 07-31-2011 15:11:21)

2)检索给定时间戳的每小时 -1 小时间隔内的请求数量。(如果开始时间戳的小时是 10 小时,结束时间戳的小时是 15 如上所述,我应该显示 7 月 13 日至 31 日之间每天 10、11、12、13、14、15 小时的每小时请求量)

查询是这样的:

WITH cal AS (
    SELECT generate_series('2-2-2011 00:00:00'::timestamp , '1-4-2012 05:00:00'::timestamp , '1 hour'::interval) AS stamp
        )
, qqq AS (
        SELECT date_trunc('hour', calltime) AS stamp
        , count(*) AS zcount
        FROM mytable
    WHERE calltime >= '13-7-2011 10:21:09' 
          AND calltime <= '31-7-2011 15:11:21' AND calltime::time >= '10:00:00' AND
          calltime::time <= '15:59:59' AND date_part('hour', calltime) >= 8 AND 
          date_part('hour', calltime) <= 15
 GROUP BY date_trunc('hour', calltime)
)
SELECT cal.stamp
        , COALESCE (qqq.zcount, 0) AS zcount
FROM cal
LEFT JOIN qqq ON cal.stamp = qqq.stamp
WHERE cal.stamp >= '13-7-2011 10:00:00' AND cal.stamp <= '31-7-2011 15:11:21' 
       AND date_part('hour', cal.stamp) >= 10 AND 
       date_part('hour', cal.stamp) <= 15
ORDER BY stamp ASC;

此查询显示 10 到 15 小时之间的请求量以每小时间隔显示(X 请求在 10:21:09 到 11:00 之间,Y 请求在 11:00 到 11:59 之间,Z 请求在 12:00 到 12 之间:59...,P 请求在 15:00 到 15:11:21 之间)从 7 月 13 日上午 10 点到下午 3 点开始到 7 月 31 日上午 10 点到下午 3 点结束的每一天

它适用于第一个时间戳的小时值小于第二个时间戳的小时值的输入——例如,在这里,第一个时间戳的小时为 10,第二个时间戳的小时为 15——但存在问题。当我想将其应用于诸如 07-13-2011 22:11:43 和 07-31-2011 04:06:04 之类的输入时,-这样我就可以得到每个小时 22 到 04 之间的请求量一天,我遇到了问题-由于我的查询结构,很可能-。我需要检索请求的总数,如下所示:

    stamp                 zcount
    "2011-07-13 22:00:00"  123
    "2011-07-13 23:00:00"  338
    "2011-07-14 00:00:00"  184
    "2011-07-13 01:00:00"  298
    "2011-07-13 02:00:00"  162
    "2011-07-13 03:00:00"  293
    "2011-07-14 04:00:00"  216
    "2011-07-14 22:00:00"  392
    "2011-07-14 23:00:00"  268
    "2011-07-15 00:00:00"  483
    "2011-07-15 01:00:00"  327
    "2011-07-15 02:00:00"  419
    "2011-07-15 03:00:00"  121
    "2011-07-15 04:00:00"  231
     .
     . 
    "2011-07-30 22:00:00"  392
    "2011-07-30 23:00:00"  268
    "2011-07-31 00:00:00"  483
    "2011-07-31 01:00:00"  327
    "2011-07-31 02:00:00"  419
    "2011-07-31 03:00:00"  544
    "2011-07-31 04:00:00"  231

我需要在查询中更改什么以确保它适用于第二个时间戳的小时值小于第一个时间戳的小时值的情况 - 例如,第一个时间戳为 22,第二个时间戳为 4 -?我目前为此使用了一种解决方法,但它并不是很优雅,我想改变它。

4

1 回答 1

4

我会诚实的。我不确定我是否接近。

我把qqq中WHERE子句中的大部分东西都去掉了,因为在外层查询的where子句中重复了。我也切换到 ISO 时间戳,因为它们对我来说更容易阅读。

您可能希望将其重写为可以传递参数的函数。

WITH cal AS (
    SELECT generate_series('2011-02-02 00:00:00'::timestamp , 
                           '2012-04-01 05:00:00'::timestamp , 
                           '1 hour'::interval) AS stamp
),
qqq AS (
  SELECT date_trunc('hour', calltime) AS stamp, count(*) AS zcount
  FROM mytable
  WHERE calltime >= '2011-07-13 20:21:09' 
    AND calltime <= '2011-07-31 15:11:21'
 GROUP BY date_trunc('hour', calltime)
)
SELECT cal.stamp, COALESCE (qqq.zcount, 0) AS zcount
FROM cal
LEFT JOIN qqq ON cal.stamp = qqq.stamp
WHERE cal.stamp >= '2011-07-13 20:00:00' 
  AND cal.stamp <= '2011-07-31 15:11:21' 
  AND (
    extract ('hour' from cal.stamp) >= extract ('hour' from '2011-07-13 20:00:00'::timestamp) or
    extract ('hour' from cal.stamp) <= extract ('hour' from '2011-07-31 15:11:21'::timestamp) 
  )
ORDER BY stamp ASC;

如果这里有什么神奇之处,它可能就在这个子句中。注意“或”的使用。

AND (
  extract ('hour' from cal.stamp) >= extract ('hour' from '2011-07-13 20:00:00'::timestamp) or
  extract ('hour' from cal.stamp) <= extract ('hour' from '2011-07-31 15:11:21'::timestamp) 
)
于 2012-09-12T02:10:49.767 回答