web-dev-qa-db-fra.com

Requête Postgresql entre les périodes

J'essaie d'interroger ma base de données postgresql pour renvoyer des résultats contenant une date correspondant à un mois et à une année donnés. En d'autres termes, je voudrais toutes les valeurs pour un mois-année.

La seule façon dont j'ai pu le faire jusqu'à présent est la suivante:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN '2014-02-01' AND '2014-02-28'

Le problème avec ceci est que je dois calculer la première date et la dernière date avant d'interroger la table. Y a-t-il un moyen plus simple de faire cela?

Merci

93
John

Avec les dates (et les heures), beaucoup de choses deviennent plus simples si vous utilisez >= start AND < end.

Par exemple:

SELECT
  user_id
FROM
  user_logs
WHERE
      login_date >= '2014-02-01'
  AND login_date <  '2014-03-01'

Dans ce cas, vous devez toujours calculer la date de début du mois dont vous avez besoin, mais celle-ci doit être simple, de plusieurs manières.

La date de fin est également simplifiée; il suffit d'ajouter exactement un mois. Pas de déconner avec les 28, 30, 31, etc.


Cette structure présente également l’avantage de pouvoir conserver l’utilisation des index.


Beaucoup de gens peuvent suggérer un formulaire tel que le suivant, mais ils () ne le font pas utilisent les index:

WHERE
      DATEPART('year',  login_date) = 2014
  AND DATEPART('month', login_date) = 2

Cela implique de calculer les conditions pour chaque ligne de la table (un balayage) et de ne pas utiliser d'index pour trouver la plage de lignes qui correspondra (une recherche de plage).

151
MatBailie

Depuis PostgreSQL 9.2 Les types de plages sont supportés. Donc, vous pouvez écrire ceci comme:

SELECT user_id
FROM user_logs
WHERE '[2014-02-01, 2014-03-01]'::daterange @> login_date

cela devrait être plus efficace que la comparaison de chaînes

Juste au cas où quelqu'un atterrirait ici ... depuis 8.1, vous pouvez simplement utiliser:

SELECT user_id 
FROM user_logs 
WHERE login_date BETWEEN SYMMETRIC '2014-02-01' AND '2014-02-28'

De la docs:

ENTRE SYMETRIQUE est identique a ENTREE sauf qu'il n'est pas nécessaire que l'argument situé à gauche de AND soit inférieur ou égal à l'argument situé à droite. Si ce n'est pas le cas, ces deux arguments sont automatiquement échangés, de sorte qu'une plage non vide est toujours implicite.

5
HayrolR