2012-03-15 33 views
20

Tôi có máy chủ với PostgreSQL 8.4 đang được khởi động lại mỗi tối lúc 01:00 (không hỏi) và cần có danh sách người dùng được kết nối (tức là dấu thời gian của họ là u.login > u.logout) :Chọn dấu thời gian của ngày hôm nay (kể từ nửa đêm) chỉ

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 

Nhưng so sánh u.login > now()-interval '24 hour' cũng cung cấp cho người dùng trước 01:00, điều tệ, đặc biệt. vào buổi sáng.

Có cách nào hiệu quả để nhận thông tin đăng nhập kể từ 01:00 sau cùng mà không làm việc nhào lộn chuỗi với to_char() không?

+1

Hihi, tôi yêu "không hỏi" :) – Mattis

Trả lời

30

Lấy cảm hứng từ nhận xét của @ Frank Tôi đã chạy một số kiểm tra và điều chỉnh truy vấn của mình cho phù hợp. Điều này phải là 1) chính xác và 2) càng nhanh càng tốt:

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; 

Vì không có dấu thời gian trong tương lai trong bảng của bạn (tôi giả định), bạn không cần giới hạn trên.
date_trunc('day', now()) gần như giống như now()::date (hoặc một số lựa chọn thay thế khác được nêu chi tiết bên dưới), chỉ có nó trả về timestamp thay vì date. Cả hai kết quả trong một timestamp anyway sau khi thêm một interval.


Biểu thức bên dưới hoạt động hơi khác. Chúng mang lại kết quả khác nhau một cách tinh tế vì localtimestamp trả về kiểu dữ liệu timestamp trong khi now() trả lại timestamp with time zone. Nhưng khi truyền tới date, hoặc được chuyển đổi thành cùng một ngày địa phươngtimestamp [without time zone] được coi là theo múi giờ địa phương. Vì vậy, khi so sánh với timestamp with time zone tương ứng, tất cả đều dẫn đến dấu thời gian UTC cùng nội bộ. Chi tiết về xử lý múi giờ trong this related question.

Tốt nhất trong số năm. Thử nghiệm với PostgreSQL 9.0. Lặp đi lặp lại với 9.1.5: kết quả nhất quán trong biên độ lỗi 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 rõ ràng là hơi nhanh hơn CURRENT_DATE.

+0

Cảm ơn bạn. Có một diễn viên từ ngày để dấu thời gian chi phí bất cứ điều gì? –

+0

@AlexanderFarber: Tất nhiên là có - ngay cả khi rất ít. –

+0

@Erwin Brandstetter: Nhưng 'date_trunc ('day', now())' có thể có giá cao hơn, bạn có nghĩ vậy không? –

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

Một cách dễ dàng để nhận tem chỉ có thời gian cho ngày hiện tại kể từ 1:00 là để lọc với CURRENT_DATE + interval '1 hour'

Vì vậy, câu hỏi của bạn sẽ trông như thế này:

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; 

Hy vọng rằng giúp.

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

Điều này phù hợp với tôi - nó chọn TẤT CẢ các hàng có ngày hôm nay.

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

Điều này phù hợp với tôi!

Các vấn đề liên quan