54 votes

Détecter les plages de dates qui se chevauchent dans une même table

J'ai un tableau avec les données suivantes

PKey  Start       End         Type
====  =====       ===         ====
01    01/01/2010  14/01/2010  S
02    15/01/2010  31/01/2010  S
03    05/01/2010  06/01/2010  A

Et je veux obtenir les résultats suivants

PKey  Start       End         Type
====  =====       ===         ====
01    01/01/2010  14/01/2010  S
03    05/01/2010  06/01/2010  A

Des idées pour commencer ? Une grande partie de la lecture que j'ai faite suggère que je dois créer des entrées pour chaque jour et les joindre les jours correspondants, est-ce la seule façon ?

0 votes

01 ne se chevauche pas 02 . Pourquoi voudriez-vous vous débarrasser de 02 ?

0 votes

J'ai compris que cela signifiait : sélectionner les lignes où l'intervalle défini dans la ligne chevauche tout intervalle défini dans d'autres lignes.

0 votes

Je cherche des enregistrements qui se chevauchent entre les types S et A.

51voto

SWeko Points 17524

Si vous avez déjà des entrées pour chaque jour, cela devrait fonctionner, mais si vous n'en avez pas, les frais généraux sont importants, et si cette requête est utilisée souvent, cela affectera les performances.

Si les données sont dans ce format, vous pouvez détecter les chevauchements en utilisant une simple arithmétique de date, car un chevauchement est simplement un intervalle qui commence après un intervalle donné, mais avant que celui-ci soit terminé, quelque chose comme

select dr1.* from date_ranges dr1
inner join date_ranges dr2
on dr2.start > dr1.start -- start after dr1 is started
  and dr2.start < dr1.end -- start before dr1 is finished

Si vous avez besoin d'un traitement spécial pour les intervalles qui sont entièrement dans un autre intervalle, ou si vous avez besoin de fusionner des intervalles, c'est à dire

PKey  Start       End         Type
====  =====       ===         ====
01    01/01/2010  20/01/2010  S
02    15/01/2010  31/01/2010  S

donnant accès à

Start       End         Type
=====       ===         ====
01/01/2010  31/01/2010  S

vous aurez besoin de calculs plus complexes.

D'après mon expérience de ce genre de problèmes, une fois que vous avez appris à faire le calcul à la main, il est facile de le transférer en SQL :)

14voto

bobfet1 Points 555

Lorsque j'ai eu besoin de comparer deux périodes de temps dans SQL for overlap, voici les quatre scénarios auxquels j'ai pu penser :

  1. Le début de la plage 1 est compris entre le début de la plage 2 et la fin de la plage 2.
  2. La fin de la travée 1 est comprise entre le début de la travée 2 et la fin de la travée 2.
  3. Le début et la fin de la plage 1 sont tous deux situés entre le début et la fin de la plage 2.
  4. Le début et la fin de Span2 sont tous les deux entre le début de Span1 et la fin de Span1.

Voici l'instruction OR que j'ai créée pour capturer ces scénarios (dans mon cas, Oracle SQL) :

and (
    s1.start between s2.start and s2.end
    OR
    s1.end between s2.start and s2.end
    OR
    s2.start between s1.start and s1.end
)

4voto

Muiz Nadeem Points 1

Si vous utilisez PostgreSQL, utilisez simplement la fonction intégrée chevauchement opérateur

SELECT (DATE '2021-01-01', DATE '2021-04-09') 
OVERLAPS (DATE '2021-01-20', DATE '2021-02-10');

4voto

Fionnuala Points 67259

Peut-être :

SELECT A.PKey, A.Start, A.End, A.Type
FROM calendar AS A, calendar AS B
WHERE (p.pkey<>a.pkey
AND b.start>=a.start
AND b.end<=a.end)
OR (b.pkey<>a.pkey
AND b.start<=a.start
AND b.end>=a.end)

3voto

davek Points 12514
select A.*
from MyTable A
inner join MyTable B
on (B.start <= A.end)
and (B.end >= A.start)

ou quelque chose comme ça (en supposant que les dates ne sont pas annulables et que des dates égales comptent comme un chevauchement).

0 votes

Cela permettra de détecter les intervalles qui sont des sous-intervalles dans le tableau, mais pas le scénario lundi-vendredi et mardi-dimanche.

0 votes

Je ne vous suis pas : si A représente le lundi-vendredi et B le mardi-dimanche, alors la première condition est remplie.

0 votes

Je me suis trompé, j'ai pris le "ou" pour un "et". Cependant, ceci retournera une intersection pour tout B qui commence avant la fin de A, même si c'est avant le début de A (A=fri-sun ; B=mon-tue).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X