Maison > base de données > tutoriel mysql > Comment calculer les heures de travail entre deux dates dans PostgreSQL, en excluant les week-ends et en tenant compte d'heures de travail spécifiques ?

Comment calculer les heures de travail entre deux dates dans PostgreSQL, en excluant les week-ends et en tenant compte d'heures de travail spécifiques ?

Patricia Arquette
Libérer: 2024-12-29 06:56:11
original
683 Les gens l'ont consulté

How to Calculate Working Hours Between Two Dates in PostgreSQL, Excluding Weekends and Considering Specific Working Hours?

Calculer les heures de travail entre 2 dates dans PostgreSQL

Problème :

Étant donné deux horodatages, déterminer le nombre d'heures de travail entre eux, considérant les week-ends comme des jours chômés et que les horaires de travail sont de 8h00 à 3h00 PM.

Exemples :

  • Horodatage : du 3 décembre à 14h00 au 4 décembre à 9h00
  • Horaires de travail : 2 heures (3 décembre = 1 heure, 4 décembre = 1 heure)
  • Horodatage : 3 décembre, 15h00 au 7 décembre, 8h00
  • Heures de travail : 8 heures (3 décembre = 0 heure, 4 décembre = 8 heures, 5 décembre = 0 heure, 6 décembre = 0 heure, 7 décembre = 0 heure)

Solution - Résultats arrondis :

SELECT count(*) AS work_hours
FROM   generate_series (timestamp '2013-06-24 13:30',
                      timestamp '2013-06-24 15:29' - interval '1h',
                      interval '1h') h
WHERE  EXTRACT(ISODOW FROM h) < 6
AND    h::time >= '08:00'
AND    h::time <= '14:00';
Copier après la connexion

Solution - Plus Précision :

L'utilisation d'unités de temps plus petites (par exemple, tranches de 5 minutes) permet plus de précision :

SELECT count(*) * interval '5 min' AS work_interval
FROM   generate_series (timestamp '2013-06-24 13:30',
                      timestamp '2013-06-24 15:29' - interval '5 min',
                      interval '5 min') h
WHERE  EXTRACT(ISODOW FROM h) < 6
AND    h::time >= '08:00'
AND    h::time <= '14:55';
Copier après la connexion

Solution - Résultats exacts :

Pour des résultats exacts jusqu'au niveau de la microseconde, utilisez l'approche suivante :

SELECT t_id
     , COALESCE(h.h, '0')  -- add / subtract fractions
       - CASE WHEN EXTRACT(ISODOW FROM t_start) < 6
               AND t_start::time > v_start
               AND t_start::time < v_end
         THEN t_start - date_trunc('hour', t_start)
         ELSE '0'::interval END
       + CASE WHEN EXTRACT(ISODOW FROM t_end) < 6
               AND t_end::time > v_start
               AND t_end::time < v_end
         THEN t_end - date_trunc('hour', t_end)
         ELSE '0'::interval END                 AS work_interval
FROM   t CROSS JOIN var
LEFT   JOIN (  -- count full hours, similar to above solutions
   SELECT t_id, count(*)::int * interval '1h' AS h
   FROM  (
      SELECT t_id, v_start, v_end
           , generate_series (date_trunc('hour', t_start)
                            , date_trunc('hour', t_end) - interval '1h'
                            , interval '1h') AS h
      FROM   t, var
      ) sub
   WHERE  EXTRACT(ISODOW FROM h) < 6
   AND    h::time >= v_start
   AND    h::time <= v_end - interval '1h'
   GROUP  BY 1
   ) h USING (t_id)
ORDER  BY 1;
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal