2009-04-14 4 views

Répondre

5

La fonction suivante renvoie le nombre de jours de week-end complet entre deux dates. Comme vous avez besoin de jours entiers, vous pouvez convertir les horodatages en dates avant d'appeler la fonction. Il renvoie 0 dans le cas où la première date n'est pas strictement antérieure à la seconde.

CREATE FUNCTION count_full_weekend_days(date, date) 
    RETURNS int AS 
$BODY$ 
    SELECT 
    ($1 < $2)::int 
     * 
    (
     (($2 - $1)/7) * 2 
     + 
     (EXTRACT(dow FROM $1)<6 AND EXTRACT(dow FROM $2)>0 AND EXTRACT(dow FROM $1)>EXTRACT(dow FROM $2))::int * 2 
     + 
     (EXTRACT(dow FROM $1)=6 AND EXTRACT(dow FROM $2)>0)::int 
     + 
     (EXTRACT(dow FROM $2)=0 AND EXTRACT(dow FROM $1)<6)::int 
    ); 
$BODY$ 
    LANGUAGE 'SQL' IMMUTABLE STRICT; 

Exemples:

SELECT COUNT_FULL_WEEKEND_DAYS('2009-04-10', '2009-04-20'); 
# returns 4 

SELECT COUNT_FULL_WEEKEND_DAYS('2009-04-11', '2009-04-20'); 
# returns 3 (11th is Saturday, so it shouldn't be counted as full day) 

SELECT COUNT_FULL_WEEKEND_DAYS('2009-04-12', '2009-04-20'); 
# returns 2 (12th is Sunday, so it shouldn't be counted as full day) 

SELECT COUNT_FULL_WEEKEND_DAYS('2009-04-13', '2009-04-20'); 
# returns 2 

Pour obtenir le nombre de jours, sauf jours du week-end complet, il suffit de soustraire le nombre de jours de la fonction ci-dessus:

SELECT 
    '2009-04-20'::date 
    - 
    '2009-04-13'::date 
    - 
    COUNT_FULL_WEEKEND_DAYS('2009-04-13', '2009-04-20'); 
1

(jours/7) * 2 + numéro de sat/sun dans les derniers jours (jours% 7).

1

Cela devrait répondre à la deuxième partie de votre question:

create or replace function is_weekend_day(date) returns boolean 
strict immutable language 'sql' 
as $$ select case extract(dow from $1) when 0 then true when 6 then true else false end $$; 

create or replace function count_weekend_days(start_date date, end_date date) returns int 
strict immutable language 'sql' 
as $$ 
select cast(sum(case when is_weekend_day($1 + ofs) then 1 else 0 end) as int) 
from generate_series(0, $2 - $1) ofs 
$$; 

Faire un count_non_weekend_days est simple correspondant après.

1

La meilleure solution à cela sera d'utiliser une table de calendrier. Ceci est incroyablement utile et vous pouvez faire toutes sortes de choses intéressantes - y compris compter le nombre de jours ouvrables entre deux dates ou compter le nombre de jours fériés entre deux dates.

Cette table est habituellement remplie à l'avance - disons pendant 20 ans avec la date pour les jours fériés connus bien étiquetés. Si les vacances changent, vous maintenez la table de temps en temps pour marquer les jours comme jours fériés. More info here et here. Cela utilise MS SQL Server, mais est également facilement porté.

0

Cela comptera le nombre d'un certain jour entre deux dates:

-- 0 Sunday 
-- 1 Monday 
-- 2 Tuesday 
-- 3 Wednesday 
-- 4 Thursday 
-- 5 Friday 
-- 6 Saturday 

WITH rng AS (
    SELECT 
     'march 3 2013'::date AS start, 
     'march 3 2014'::date AS end, 
     0     AS day -- Sunday 
) 

SELECT count(1) 
FROM rng, generate_series(0, (extract(epoch from age(rng.end, rng.start))/(60*60*24))::int) AS n 
WHERE extract(dow from rng.start + (n * '1 day'::interval)) = rng.day 
0

Je vous suggère de créer une fonction à utiliser quand vous voulez et écrire moins;

Ce code ci-dessus va créer une fonction sql qui compte et retourne le nombre de jours de week-end (Sam, Dim). Juste la façon dont vous aurez plus de flexibilité pour utiliser cette fonction.

CREATE OR REPLACE FUNCTION <YourSchemaNameOptional>.count_full_weekend_days(date, date) 
RETURNS bigint AS 
$BODY$ 
     select COUNT(MySerie.*) as Qtde 
     from (select CURRENT_DATE + i as Date, EXTRACT(DOW FROM CURRENT_DATE + i) as DiaDate 
       from generate_series(date ($1) - CURRENT_DATE, date ($2) - CURRENT_DATE) i) as MySerie 
     WHERE MySerie.DiaDate in (6,0); 
$BODY$ 
LANGUAGE 'SQL' IMMUTABLE STRICT; 

Après cela, vous pouvez utiliser la fonction pour revenir seulement le nombre de jours de week-end dans un intervalle. Voici l'exemple d'utilisation:

SELECT <YourSchemaNameOptional>.count_full_weekend_days('2017-09-11', '2017-09-25') as days; --> RES: 4 

Cette sélection doit revenir à quatre parce que le premier et le deuxième jour du lundi, et nous avons 2 le samedi et le dimanche 2 entre eux.

Maintenant, pour revenir seulement jours ouvrables (sans week-end), que vous voulez, juste faire une soustraction, comme dans l'exemple ci-dessous:

SELECT (date '2017-09-25' - date '2017-09-11') - <YourSchemaName>.count_full_weekend_days('2017-09-11', '2017-09-25'); --> RES: 14 - 4 = 10 
2

Vous trouverez peut-être ce vraiment utile:

CREATE OR REPLACE FUNCTION working_days(date, date) RETURNS INT AS 
$$ 
SELECT COUNT(days)::INT 
    FROM generate_series($1, $2, '1 day') AS days 
    WHERE EXTRACT(DOW FROM days) NOT IN(0, 6); 
$$ 
LANGUAGE 'sql' IMMUTABLE STRICT; 
Questions connexes