84 votes

Vérifier le chevauchement des plages de dates dans MySQL

Cette table est utilisée pour stocker les sessions (événements) :

CREATE TABLE session (
  id int(11) NOT NULL AUTO_INCREMENT
, start_date date
, end_date date
);

INSERT INTO session
  (start_date, end_date)
VALUES
  ("2010-01-01", "2010-01-10")
, ("2010-01-20", "2010-01-30")
, ("2010-02-01", "2010-02-15")
;

Nous ne voulons pas qu'il y ait de conflit entre les gammes.
Disons que nous devons insérer une nouvelle session à partir de 2010-01-05 a 2010-01-25 .
Nous aimerions connaître la ou les sessions en conflit.

Voici ma question :

SELECT *
FROM session
WHERE "2010-01-05" BETWEEN start_date AND end_date
   OR "2010-01-25" BETWEEN start_date AND end_date
   OR "2010-01-05" >= start_date AND "2010-01-25" <= end_date
;

Voici le résultat :

+----+------------+------------+
| id | start_date | end_date   |
+----+------------+------------+
|  1 | 2010-01-01 | 2010-01-10 |
|  2 | 2010-01-20 | 2010-01-30 |
+----+------------+------------+

Y a-t-il un meilleur moyen de l'obtenir ?


violon

1 votes

Votre troisième condition est fausse. Elle est censée être "2010-01-05" <= start_date AND "2010-01-25" >= end_date . Voir stackoverflow.com/a/28802972/632951 pour la visualisation. Votre troisième condition actuelle ne sera jamais évaluée, car la première (et la deuxième) condition la couvre déjà.

0voto

Vishal Kumar Sahu Points 529

Récemment, j'ai été confronté au même problème et j'ai fini par trouver cette étape facile (il se peut que ce ne soit pas une bonne approche ou que cela demande beaucoup de mémoire).

SELECT * FROM duty_register WHERE employee = '2' AND (
(
duty_start_date BETWEEN {$start_date} AND {$end_date}
OR
duty_end_date BETWEEN {$start_date} AND {$end_date}
)
OR
(
{$start_date} BETWEEN duty_start_date AND duty_end_date
OR
{$end_date} BETWEEN duty_start_date AND duty_end_date)
);

Cela m'a aidé à trouver les entrées dont les plages de dates se chevauchent.

J'espère que cela aidera quelqu'un.

0voto

Hussein Akar Points 1

Vous pouvez couvrir tous les cas de chevauchement de dates, même lorsque to-date dans la base de données peut éventuellement être nul, comme suit :

SELECT * FROM `tableName` t
WHERE t.`startDate` <= $toDate
AND (t.`endDate` IS NULL OR t.`endDate` >= $startDate);

Cela renverra tous les enregistrements qui chevauchent les nouvelles dates de début/fin de quelque manière que ce soit.

0voto

yg-dba Points 222

La réponse de Mackraken ci-dessus est meilleure du point de vue des performances car elle ne nécessite pas plusieurs OU pour évaluer si deux dates se chevauchent. Bonne solution !

Cependant, j'ai découvert que dans MySQL, vous devez utiliser DATEDIFF au lieu de l'opérateur moins -.

SELECT o.orderStart, o.orderEnd, s.startDate, s.endDate
, GREATEST(LEAST(orderEnd, endDate) - GREATEST(orderStart, startDate), 0)>0 as overlaps
, DATEDIFF(LEAST(orderEnd, endDate), GREATEST(orderStart, startDate)) as overlap_length
FROM orders o
JOIN dates s USING (customerId)
WHERE 1
AND DATEDIFF(LEAST(orderEnd, endDate),GREATEST(orderStart, startDate)) > 0;

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