2012-03-15 21 views
20

PostgreSQL 8.4 ile her gece 01: 00'de yeniden başlatılıyor (bağlantı yok) ve bağlı kullanıcıların listesini almaları gereken bir sunucum var (örneğin, zaman damgaları u.login > u.logout) :Günün seçimlerini (gece yarısından beri) seçtikleri zamanlar

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 

Ama u.login > now()-interval '24 hour' karşılaştırarak aynı zamanda eSP, kötü son 01:00, önce kullanıcıların sunar. sabahları.

to_char() ile dize akrobasi yapmadan son 01:00 beri oturumların almak için herhangi verimli bir yolu var mı?

+1

Hihi, "sorma" yı seviyorum :) – Mattis

cevap

30

bazı testler yaptım ve buna göre benim sorgu uyarlanmış. Bu, doğru 1) ve 2) mümkün olduğunca hızlı olmalıdır:

Tablonuzdaki hiçbir geleceği zaman damgaları bulunmadığından
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; 

(ı varsayalım), hiçbir üst sınır gerekir.
date_trunc('day', now()), now()::date (veya aşağıda ayrıntıları verilen bazı diğer alternatifler) ile aynıdır, yalnızca date yerine timestamp döndürür. Her ikisi de interval ekledikten sonra timestamp sonucunu verir. ifadeleri Aşağıda


biraz farklı gerçekleştirin. Bunlar localtimestamp döner veri türü timestampnow() ise döner timestamp with time zone için biraz farklı sonuçlar vermektedir. Ancak, date'a döküldüğünde, aynı yerel tarihine dönüştürülür ve timestamp [without time zone] yerel saat diliminde de olduğu varsayılır. Dolayısıyla, karşılık gelen timestamp with time zone ile karşılaştırıldığında, hepsi dahili olarak aynı UTC zaman damgasıyla sonuçlanır. this related question'da saat dilimi işlemeyle ilgili daha fazla bilgi.

beş iyisi. PostgreSQL 9.0 ile test edilmiştir. 9.1.5 ile tekrarlandı:% 1 hata payı içinde tutarlı sonuçlar.

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 açıkçası CURRENT_DATE biraz daha hızlıdır.

+0

Teşekkür ederim. Tarihten zaman damgasına kadar döküm herhangi bir şeye mal olur mu? –

+0

@AlexanderFarber: Tabii ki - çok az bile olsa. –

+0

@Erwin Brandstetter: Fakat 'date_trunc ('gün', şimdi())' daha pahalıya mal olabilir, sence de öyle değil mi? –

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

01:00 beri geçerli günün sadece zaman damgalarını almanın kolay bir yolu Yani sorgu gibi görünmelidir CURRENT_DATE + interval '1 hour'

ile filtre etmektir:

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; 

Umut o yardım eder. Frank'in comment @ esinlenerek

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

Bu benim için çalışır - bugünün Tarihiyle TÜM satırları seçer.

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

Bu benim için iyi çalışıyor!