Трябва да дефинирате "между две дати" по-близо. Включени или изключени долна и горна граница? Често срещано определение би било включване долната иизключита горната граница на интервал. Плюс това, дефинирайте резултата като 0, когато долната и горната граница са идентични. Това определение се случва да съвпада с изваждане на дата точно .
SELECT date '2017-01-31' - date '2017-01-01' AS days_between
Това точно определение е важно за изключване на неделята. За дадената дефиниция интервал от слънце до слънце (1 седмица по-късно) не включва горната граница, така че има само 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
, а не dow
за EXTRACT()
.
Завключване горната граница, просто заменете z - a
с (z - a) + 1
. (Би работи без скоби, поради предимство на оператора, но по-добре да е ясно.)
Характеристиката на производителността е O(1) (константа) за разлика от условен агрегат върху генериран набор с O(N) .
Свързано:
- Как да определя последния ден от предишния месец с помощта на PostgreSQL?
- Изчислете работното време между 2 дати в PostgreSQL