2017-01-26 9 views
1

Чтобы найти количество дней между двумя датами мы можем использовать что-то вроде этого:Как считать дни, кроме воскресенья между двумя датами в Postgres?

SELECT date_part('day',age('2017-01-31','2017-01-01')) as total_days; 

В приведенном выше запросе мы получили 30 в качестве вывода вместо 31. Почему это?
И я также хочу найти количество дней за исключением Воскресенье. Ожидаемые результаты для интервала ('2017-01-01', '2017-01-31'):

Total Days = 31 
Total Days except Sundays = 26 
+2

Unrelated, но: 'date_part ('день', возраст ('2017-01-31', '2017-01-01')) 'дает неверный результат, если« возраст »больше месяца. например 'date_part ('день', возраст ('2016-02-28', '2016-01-01'))' вернет 27, хотя должно быть 58. Если вы хотите количество дней между двумя датами, просто вычтите их : 'date '2017-01-31' - date '2017-01-01'' –

+0

Спасибо @a_horse_with_no_name ... будет использовать это – Mani

ответ

1

Вы можете попробовать использовать generate_series генерировать все даты между указанной датой, а затем принять количество требуемых дней.

SELECT 
    count(case when extract(dow from generate_series) <> 0 then 1 end) n 
from generate_series('2017-01-01'::date,'2017-01-31'::date, '1 day'); 
3

Вам нужно определить "между двумя датами" более близко. Нижняя и верхняя граница включены или исключены? Общее определение будет состоять из включает нижний и исключить верхний предел интервала. Кроме того, определить результат как 0, когда нижняя и верхняя границы идентичны. Это определение совпадает с вычитанием даты точно.

SELECT date '2017-01-31' - date '2017-01-01' AS days_between 

Это точное определение важно для исключения воскресений. Для данного определения интервал от Sun-Sun (1 неделя спустя) не включает верхнюю границу, поэтому есть только Воскресенье для вычитания.

interval in days | sundays 
0     | 0 
1-6    | 0 or 1 
7     | 1 
8-13    | 1 or 2 
14    | 2 
... 

Интервал 7 дней всегда включает ровно одно воскресенье.

Мы можем получить минимальный результат с помощью простого целочисленного деления (дней/7), который усекает результат.

Дополнительное воскресенье в течение 1 - 6 дней зависит от первого дня интервала. Если это воскресенье, бинго; если это понедельник, слишком плохо. И т.д. Мы можем получить простую формулу из этого:

SELECT days, sundays, days - sundays AS days_without_sundays 
FROM (
    SELECT z - a AS days 
     , ((z - a) + EXTRACT(isodow FROM a)::int - 1)/7 AS sundays 
    FROM (SELECT date '2017-01-02' AS a  -- your interval here 
       , date '2017-01-30' AS z) tbl 
    ) sub; 

Работы для любого данного интервала.
Примечание: isodow, not dow for EXTRACT().

Для включает верхней границы, просто замените z - a с (z - a) + 1. (Будет работать без скобок, из-за приоритета операторов, но лучше быть ясно.)

Эксплуатационная характеристика является O (1) (константа), в отличие от условной совокупности более сгенерированного набора с O (N).

Похожие: