2017-07-21 3 views
1

donné une table PostgreSQL qui est censé contenir des lignes avec continue, valid_range plages sans chevauchement telles que:PostgreSQL: requête pour tstzrange qui contient dernier instant d'un quart

CREATE TABLE tracking (
    id INT PRIMARY KEY, 
    valid_range TSTZRANGE NOT NULL, 
    EXCLUDE USING gist (valid_range WITH &&) 
); 

INSERT INTO tracking (id, valid_range) VALUES 
    (1, '["2017-03-01 13:00", "2017-03-31 14:00")'), 
    (2, '["2017-03-31 14:00", "2017-04-01 00:00")'), 
    (3, '["2017-04-01 00:00",)'); 

Cela crée une table qui contient:

id |      valid_range      
----+----------------------------------------------------- 
    1 | ["2017-03-01 13:00:00-07","2017-03-31 14:00:00-06") 
    2 | ["2017-03-31 14:00:00-06","2017-04-01 00:00:00-06") 
    3 | ["2017-04-01 00:00:00-06",) 

J'ai besoin d'interroger pour la ligne qui était la ligne valide à la fin d'un trimestre donné, où je suis la définition « à la fin d'un quart » comme « l'instant dans le temps juste avant la date changé pour être le premier jour du nouveau trimestre. " Dans l'exemple ci-dessus, l'interrogation pour la fin du premier trimestre 2017 (le premier trimestre se termine à la fin du 2017-03-31 et le deuxième trimestre commence le 2017-04-01), je souhaite que ma requête renvoie uniquement la ligne avec l'ID 2.

Quelle est la meilleure façon d'exprimer cette condition dans PostgreSQL?

SELECT * FROM tracking WHERE valid_range @> TIMESTAMPTZ '2017-03-31' est faux car il retourne la ligne qui contient minuit 31/03/2017, qui est ID 1.

valid_range @> TIMESTAMPTZ '2017-04-01' est également faux car il saute sur la ligne qui était en fait droit valable à la fin de le quart (ID 2) et retourne à la place la ligne avec ID 3, qui est la ligne qui commence le nouveau trimestre.

J'essaie d'éviter d'utiliser quelque chose comme ...ORDER BY valid_range DESC LIMIT 1 dans la requête.

Notez que la fin des plages doit toujours être exclusive, je ne peux pas changer cela.

+0

'SELECT * FROM suivi WHERE valid_range @> TIMESTAMPTZ '2017-03-31 23: 59: 59''? – Abelisto

+0

@Abelisto Nope, parce que je dois poser à propos de 23: 59: 59.9 et puis 23: 59: 59.99 et 23: 59: 59.999 et ... :) – Dale

+0

Si vos gammes ont une précision de plus d'une seconde - oui. Mais dans votre exemple, il est jusqu'à heure. – Abelisto

Répondre

1

La meilleure réponse que je suis venu avec est jusqu'à présent

SELECT 
    * 
FROM 
    tracking 
WHERE 
    lower(valid_range) < '2017-04-01' 
    AND upper(valid_range) >= '2017-04-01' 

Cela semble être l'équivalent moral de dire: « Je veux inverser la inclusivité/exclusivité des limites sur cette colonne TSTZRANGE pour cette requête "ce qui me fait penser qu'il me manque une meilleure façon de le faire. Je ne serais pas surpris si cela annule également les avantages des index typiques sur une colonne de plage.