2009-04-14 7 views

Antwort

5

Die folgende Funktion die Anzahl der vollen Wochenendtage zwischen zwei Daten zurückkehrt. Wenn Sie ganze Tage benötigen, können Sie die Zeitstempel auf Daten vor dem Aufruf der Funktion umwandeln. Es gibt 0 zurück, wenn das erste Datum nicht genau vor dem zweiten liegt.

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; 

Beispiele:

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 

Um die Anzahl der Tage außer vollen Wochenende Tage zu erhalten, subtrahieren Sie einfach die Anzahl der Tage von der Funktion oben:

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

(Tage/7) * 2 + Anzahl von Sat/Sonne in den letzten Tagen (Tage% 7).

1

Dies sollte den zweiten Teil Ihrer Frage beantworten:

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 
$$; 

machen eine entsprechende count_non_weekend_days danach einfach.

1

Die beste Lösung hierfür ist die Verwendung einer Kalendertabelle. Das ist unglaublich nützlich und Sie können alle möglichen interessanten Dinge tun - einschließlich der Anzahl der Arbeitstage zwischen zwei Daten oder der Anzahl der Feiertage zwischen zwei Daten.

Diese Tabelle wird normalerweise im Voraus ausgefüllt - sagen Sie für 20 Jahre mit dem Datum für bekannte Feiertage entsprechend markiert. Wenn Feiertage verschoben werden, pflegen Sie die Tabelle ab und zu, um die Tage als Feiertage zu markieren. More info here und here. Dies verwendet MS SQL Server, kann aber auch leicht portiert werden.

0

Dadurch wird die Anzahl zählen von einem bestimmten Tag zwischen zwei Daten:

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

Ich empfehle Ihnen, eine Funktion für die Verwendung zu erstellen, wann immer Sie wollen und weniger schreiben;)

Dieser Code oben erstellt eine SQL-Funktion, die die Anzahl der Wochenendtage (Sa, So) zählt und zurückgibt. Genau so haben Sie mehr Flexibilität, um diese Funktion zu nutzen.

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; 

Danach können Sie die Funktion nutzen nur die Anzahl der Wochentage in einem Intervall zurückzukehren. Hier ist das Beispiel zu verwenden:

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

Diese Auswahl vier zurückgeben muss, da der erste und der zweite Tag Montag, und wir haben zwei Samstagen und Sonntagen 2 zwischen ihnen.

Nun zurückzukehren nur Werktage (ohne Wochenende), wie Sie wollen, nur eine Subtraktion machen, wie im folgenden Beispiel:

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

Sie finden könnte dies wirklich hilfreich:

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; 
Verwandte Themen