Musíte definovat "mezi dvěma daty" blíže. Dolní a horní hranice zahrnuta nebo vyloučena? Běžnou definicí by bylo zahrnout nižší a vyloučit horní mez intervalu. Navíc definujte výsledek jako 0, když jsou spodní a horní mez identické. Tato definice se náhodou shoduje s odečítáním data přesně .
SELECT date '2017-01-31' - date '2017-01-01' AS days_between
Tato přesná definice je důležitá pro vyloučení nedělí. Pro danou definici interval od Slunce do Slunce (o 1 týden později) nezahrnuje horní hranici, takže existuje pouze 1 Neděle k odečtení.
interval in days | sundays
0 | 0
1-6 | 0 or 1
7 | 1
8-13 | 1 or 2
14 | 2
...
Interval 7 dní zahrnuje vždy přesně jednu neděli.
Minimální výsledek můžeme získat jednoduchým celočíselným dělením (dny / 7 ), což zkrátí výsledek.
Neděle navíc pro zbytek 1 - 6 dnů závisí na prvním dni intervalu. Pokud je neděle, bingo; pokud je pondělí, škoda. Atd. Můžeme z toho odvodit jednoduchý vzorec:
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;
Funguje pro jakékoli daný interval.
Poznámka:isodow
, nikoli dow
pro EXTRACT()
.
Chcete-li zahrnout horní hranici, stačí nahradit z - a
s (z - a) + 1
. (Fungovalo by to bez závorek, kvůli prioritě operátorů, ale je lepší být jasný.)
Výkonnostní charakteristika je O(1) (konstanta) na rozdíl od podmíněné agregace nad vygenerovanou množinou s O(N) .
Související:
- Jak pomocí PostgreSQL určím poslední den předchozího měsíce?
- Vypočítejte pracovní dobu mezi 2 daty v PostgreSQL