2012-03-15 2 views
20

매일 밤 01:00에 재부팅되는 PostgreSQL 8.4가 설치된 서버가 있는데 (묻지 않음) 연결된 사용자 목록을 가져와야합니다 (즉, 시간 소인은 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'을 비교하는 것도 ESP, 나쁜 마지막 1시 전에 사용자를 제공합니다. 아침에.

효율적인 방법이 있습니까 to_char()으로 문자열 곡예를하지 않고 마지막 01:00 이후에 로그인을 얻으십니까?

+1

안녕하세요, "물어 보지 마세요"를 좋아합니다. :) – Mattis

답변

30

@ Frank의 의견에 영감을 받아 몇 가지 테스트를 실행하고 적절하게 쿼리를 수정했습니다. 이것은 올바른 1)과 2) 가능한 한 빨리해야한다 :

테이블에서 미래의 타임 스탬프가 없기 때문에
SELECT u.login, u.id, u.first_name 
FROM pref_users u 
WHERE u.login > u.logout 
AND u.login >= now()::date + interval '1h' 
ORDER BY u.login; 

(나는 가정), 당신은 더 상한을 필요가 없습니다.
date_trunc('day', now())now()::date (또는 아래에 설명 된 다른 대안)과 거의 동일하며 date 대신 timestamp을 반환합니다. 두 가지 모두 interval을 추가 한 후에 timestamp이 표시됩니다.


아래 표현식은 약간 다르게 수행됩니다. localtimestamp은 데이터 형식 timestamp을 반환하고 now()timestamp with time zone을 반환하므로 미묘하게 다른 결과가 나타납니다. 그러나 date으로 캐스트하면 어느 쪽이나 로컬 날짜로 변환되고 timestamp [without time zone]은 현지 시간대로 추정됩니다. 따라서 대응하는 timestamp with time zone과 비교하면 내부적으로 동일한 UTC 타임 스탬프가됩니다. this related question의 시간대 처리에 대한 자세한 내용.

최고 5 개. PostgreSQL 9.0에서 테스트되었습니다. 9.1.5 반복 : 1 % 오차 범위 내에서 일관된 결과.

SELECT localtimestamp::date  + interval '1h' -- Total runtime: 351.688 ms 
    , current_date    + interval '1h' -- Total runtime: 338.975 ms 
    , date_trunc('day', now()) + interval '1h' -- Total runtime: 333.032 ms 
    , now()::date    + interval '1h' -- Total runtime: 278.269 ms 
FROM generate_series (1, 100000) 

now()::date 분명히 CURRENT_DATE보다 약간 빠릅니다.

+0

감사합니다. 날짜에서 시간 소인까지의 캐스트에 비용이 들지 않습니까? –

+0

@AlexanderFarber : 물론 그렇습니다. –

+0

@Erwin Brandstetter : 그러나'date_trunc ('day', now())'는 더 많은 비용이들 것입니다. 그렇습니까? –

3
where 
    u.login > u.logout 
    and  
    date_trunc('day', u.login) = date_trunc('day', now()) 
    and 
    date_trunc('hour', u.login) >= 1 
9

1시 때문에 현재 일에 대해서만 타임 스탬프를 얻는 쉬운 방법은 그래서 쿼리는 다음과 같아야합니다 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; 

희망 도움이됩니다.

3
select * from termin where DATE(dateTimeField) >= CURRENT_DATE AND DATE(dateTimeField) < CURRENT_DATE + INTERVAL '1 DAY' 

이것은 나를 위해 일합니다 - 오늘 날짜가있는 모든 행을 선택합니다.

4
select * from termin where DATE(dateTimeField) = '2015-11-17' 

이것은 잘 작동합니다.