2009-04-14 7 views
2

Учитывая, что 2 временных метки в postgres, как вы вычисляете разницу во времени без учета всех суббот и воскресенья?Получение числа определенных дней недели (выходных) с интервалом в PostgreSQL

ИЛИ

Как посчитать количество субботам и воскресеньям в заданном интервале времени?

ответ

5

Следующая функция возвращает количество полных выходных дней между двумя датами. Поскольку вам нужны полные дни, вы можете назначить метки времени для дат перед вызовом функции. Он возвращает 0, если первая дата не строго до второй.

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; 

Примеры:

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 

Чтобы получить количество дней, за исключением полных выходных дней, просто вычесть число дней с указанной выше функции:

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

(дни/7) * 2 + количество сидений/солнца в последние (дни% 7) дней.

1

Это должно ответить на вторую часть вашего вопроса:

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

Создание соответствующего count_non_weekend_days просто после этого.

1

Лучшим решением для этого будет использование таблицы календаря. Это невероятно полезно, и вы можете делать всевозможные интересные вещи, включая подсчет количества рабочих дней между двумя датами или подсчет количества праздников между двумя датами.

Эта таблица, как правило, заселена заранее - скажем, в течение 20 лет с датой для известных праздников, соответствующим образом помеченной. Если праздничные дни смещаются, вы иногда поддерживаете таблицу, чтобы отметить дни как праздники. More info here и here. Это использует MS SQL Server, но также легко переносится.

0

Это будет подсчитывать количество определенного дня между двумя датами:

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

Я предлагаю вам создать функцию для использования, когда захотите и напишите меньше;)

Этот код, указанный выше, создаст функцию sql, которая подсчитывает и возвращает количество выходных дней (сб, вс). Как раз у вас будет больше возможностей использовать эту функцию.

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; 

После этого, вы можете использовать функцию вернуть только количество выходных дней в интервале. Вот пример использования:

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

Этот выбор должен вернуть четыре, так как первый и второй день в понедельник, и у нас есть 2 субботы и 2 воскресенья между ними.

Теперь вернуться только рабочих дней (без выходных), , как вы хотите, просто сделать вычитание, как в примере ниже:

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

Вы могли бы найти это действительно полезно:

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; 

 Смежные вопросы

  • Нет связанных вопросов^_^