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
639 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!

source:php.cn
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