J'ai un serveur avec PostgreSQL 8.4 qui redémarre tous les soirs à 01h00 (ne demandez pas) et j'ai besoin d'obtenir une liste des utilisateurs connectés (c'est-à-dire que leurs horodatages sont 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
Mais la comparaison de u.login > now()-interval '24 hour'
fournit également les utilisateurs avant le dernier 01:00, ce qui est mauvais, en particulier. les matins.
Existe-t-il un moyen efficace de obtenir les connexions depuis le dernier 01: sans faire d'acrobatie avec to_char()
?
Inspiré par le commentaire de @ Frank, j'ai effectué quelques tests et adapté ma requête en conséquence. Cela devrait être 1) correct et 2) le plus rapidement possible:
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;
Comme il n'y a pas d'horodatage futur dans votre table (je suppose), vous n'avez pas besoin de limite supérieure.date_trunc('day', now())
est presque la même chose que now()::date
(ou quelques autres alternatives détaillées ci-dessous), seulement qu'elle renvoie timestamp
au lieu d'un date
. Les deux résultent en un timestamp
de toute façon après avoir ajouté un interval
.
Les expressions ci-dessous fonctionnent légèrement différemment. Ils donnent des résultats subtilement différents parce que localtimestamp
renvoie le type de données timestamp
tandis que now()
renvoie timestamp with time zone
. Mais lorsqu'il est converti en date
, l'un ou l'autre est converti à la même date locale , et un timestamp [without time zone]
Est présumé être dans le fuseau horaire local aussi. Ainsi, par rapport au timestamp with time zone
Correspondant, ils entraînent tous le même horodatage UTC en interne. Plus de détails sur la gestion des fuseaux horaires dans cette question connexe .
Le meilleur des cinq. Testé avec PostgreSQL 9.0. Répété avec 9.1.5: résultats cohérents dans une marge d'erreur de 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
est évidemment légèrement plus rapide que CURRENT_DATE
.
Un moyen simple d'obtenir uniquement des horodatages pour la journée en cours depuis 01h00 consiste à filtrer avec CURRENT_DATE + interval '1 hour'
Votre requête devrait donc ressembler à ceci:
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;
J'espère que cela pourra aider.
select * from termin where DATE(dateTimeField) >= CURRENT_DATE AND DATE(dateTimeField) < CURRENT_DATE + INTERVAL '1 DAY'
Cela fonctionne pour moi - il sélectionne TOUTES les lignes avec la date d'aujourd'hui.
select * from termin where DATE(dateTimeField) = '2015-11-17'
Cela fonctionne bien pour moi!
where
u.login > u.logout
and
date_trunc('day', u.login) = date_trunc('day', now())
and
date_trunc('hour', u.login) >= 1