48

我有一个 PostgreSQL 8.4 的服务器,它每天晚上 01:00 重新启动(不要问),并且需要获取连接用户的列表(即他们的时间戳是u.login > u.logout):

SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout and 
      u.login > now() - interval '24 hour'
ORDER BY u.login;

           login            |           id   | first_name
----------------------------+----------------+-------------
 2012-03-14 09:27:33.41645  | OK171511218029 | Alice
 2012-03-14 09:51:46.387244 | OK448670789462 | Bob
 2012-03-14 09:52:36.738625 | OK5088512947   | Sergej

但是比较u.login > now()-interval '24 hour'也会在最后 01:00 之前交付用户,这很糟糕,尤其是。在早上。

自上次 01:00 以来,是否有任何有效的方法可以在不使用字符串杂技的情况下获取登录信息to_char()

4

6 回答 6

69

这应该是 1)正确和 2)尽可能快:

SELECT u.login, u.id, u.first_name
FROM   pref_users u
WHERE  u.login >= now()::date + interval '1h'
AND    u.login > u.logout
ORDER  BY u.login;

由于您的表中没有未来的时间戳(我假设),因此您不需要上限。

一些等价的表达:

SELECT localtimestamp::date     + interval '1h'
     , current_date             + interval '1h'
     , date_trunc('day', now()) + interval '1h'
     , now()::date              + interval '1h'

now()::date过去的执行速度比CURRENT_DATE旧版本稍快,但在现代 Postgres 中不再如此。但LOCALTIMESTAMP出于某种原因,两者都比 Postgres 14 更快。

date_trunc('day', now()) + interval '1h'略有不同的是它返回timestamptz。但是它被强制timestamp根据timezone当前会话的设置与timestamp列相比login,效果相同。

看:


要返回前一天的行而不是在当地时间 00:00 和 01:00 之间发出时不返回任何内容,请改用:

WHERE  u.login >= (LOCALTIMESTAMP - interval '1h')::date + interval '1h'
于 2012-03-15T09:37:51.447 回答
18
select * from termin where DATE(dateTimeField) >= CURRENT_DATE AND DATE(dateTimeField) < CURRENT_DATE + INTERVAL '1 DAY'

这对我有用 - 它选择今天日期的所有行。

于 2015-07-04T17:37:28.747 回答
16
select * from termin where DATE(dateTimeField) = '2015-11-17'

这对我很有效!

于 2015-11-17T07:57:10.690 回答
14

从 01:00 开始仅获取当天时间戳的一种简单方法是使用 CURRENT_DATE + interval '1 hour'

所以你的查询应该是这样的:

SELECT u.login, u.id, u.first_name
FROM pref_users u
WHERE u.login > u.logout AND
      u.login > CURRENT_DATE + interval '1 hour'
ORDER BY u.login;

希望有帮助。

于 2012-03-15T09:34:09.000 回答
4
where 
    u.login > u.logout 
    and     
    date_trunc('day', u.login) = date_trunc('day', now()) 
    and 
    date_trunc('hour', u.login) >= 1
于 2012-03-15T09:29:31.237 回答
0

到目前为止,所有答案都是不正确的,因为它们给出了 0.00 到 1.00 之间的错误答案。因此,如果您碰巧在该时间段内运行查询,您将得不到任何结果。根据@ErwinBrandstetter 的回答,你想要的是:

WHERE u.login > u.logout
AND u.login >= CASE WHEN NOW()::time < '1:00'::time THEN NOW()::date - INTERVAL '23 HOUR' ELSE NOW()::date + INTERVAL '1 HOUR' END;

我很想没有条件但找不到办法。

编辑:@ErwinBrandstetter 确实在没有条件的情况下这样做了,为了完整性而将其留在这里。

于 2022-01-31T00:56:04.947 回答