Sélection par date avec intervalle

L'auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Salut,

J'aimerais pouvoir faire une requête qui sélectionne les données en fonction de la date, mais avec une intervalle.

Par exemple j'ai ces dates :

1
2
3
4
5
6
7
2016-05-15 18:15:20+00
2016-05-15 18:16:20+00
2016-05-15 18:17:20+00
2016-05-15 18:18:20+00
2016-05-15 18:19:20+00
2016-05-15 18:20:20+00
2016-05-15 18:21:20+00

Et j'aimerais sélectionner toutes les 3 minutes en partant de la dernière :

1
2
3
2016-05-15 18:21:20+00
2016-05-15 18:18:20+00
2016-05-15 18:15:20+00

Existe-t-il un moyen intégré à PostgreSQL pour y parvenir ?

Merci :)

+0 -0
Staff

Cette réponse a aidé l'auteur du sujet

Pour un intervalle, il y a between

1
2
3
SELECT *
FROM tatable
WHERE date_field BETWEEN DATE_SUB(NOW(), INTERVAL 3 MINUTES) AND NOW()

Notons que "toutes les 3 minutes en partant de la dernière" c'est pas un intervalle. On aura plutôt:

1
2
3
SELECT *
FROM tatable
WHERE (MINUTE(NOW()) - MINUTE(date_field)) % 3 = 0
+2 -0

Cette réponse a aidé l'auteur du sujet

Il faut que tu regardes du côté des fonctions de fenêtrage si c'est bien basé sur la "position" des lignes et que tu n'en connais pas vraiment à l'avance la valeur.

Genre :

1
2
3
4
5
6
7
8
SELECT * FROM (
    SELECT row_number() OVER () AS rank, *
        FROM table
        ORDER BY colonne DESC
) t
WHERE rank % 3 = 1 -- la première est numérotée 1, pas 0
LIMIT 3
;

Édité par vibrice

+1 -0

La requête est surement moins performante et moins facile d'utilisation que celle proposé par artragis (première réponse du sujet).

Une troisième idée, la fonction generate_series. Vous êtes obligé de faire trois sous requêtes.

L'idée générale (non testé) :

1
2
3
4
5
6
7
8
select date(d) as day 
from generate_series(
  (SELECT min(date) FROM maTable LIMIT 1), 
  (SELECT max(date) FROM maTable LIMIT 1), 
  '3 minutes'
) d 
left join maTable on date(date) = d 
group by d order by d desc;

La question est de savoir si c'est assez performant pour votre cas d'utilisation. On pourrait réfléchir, à faire les deux requêtes qui récupère le minimum et le maximum avant dans un langage de programmation delta, les stocker dans un cache ou les récupérer si elle existe déjà dans le cache. Vous évitant ainsi une perte de performance.

Édité par Hugo

Auteur du sujet

Merci à vous pour l'aide ! J'ai testé les solution d'artragis, mais effectivement pour la première ce n'est pas ce que je recherche (pour l'implémentation de la première solution j'ai du faire quelques adaptations :

sql SELECT id,date,value FROM cycles_cameramoduleresult WHERE date BETWEEN (NOW()- '3 MINUTES'::INTERVAL) AND NOW() ). Et pour la deuxième solution, malheureusement, je ne connais pas à l'avance "l'intervalle" (ça peut être 1h, 10 minutes, 1 jour, etc.).

J'ai testé la solution de vibrice (juste pour tester avec un WHERE rank/3=1, cela fonctionne). Par contre dès que je mets le modulo, ça plante ("tuple index out of range"), je cherche pourquoi.

Je n'ai pas encore eu l'occasion de tester la solution d'Hugo :)

Edit :

Bon.. en fait j'utilise la mauvaise syntaxe, c'est mod(rank,3) et non rank%3 :p

Édité par Chaoxys

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte