Debe definir "entre dos fechas" más cerca. ¿Límite inferior y superior incluidos o excluidos? Una definición común sería incluir el inferior y excluir el límite superior de un intervalo. Además, defina el resultado como 0 cuando el límite superior e inferior sean idénticos. Esta definición coincide con la resta de fecha exactamente .
SELECT date '2017-01-31' - date '2017-01-01' AS days_between
Esta definición exacta es importante para excluir los domingos. Para la definición dada, un intervalo de Sun - Sun (1 semana después) no incluye el límite superior, por lo que solo hay 1 Domingo a restar.
interval in days | sundays
0 | 0
1-6 | 0 or 1
7 | 1
8-13 | 1 or 2
14 | 2
...
Un intervalo de 7 días siempre incluye exactamente un domingo.
Podemos obtener el resultado mínimo con una simple división de enteros (días / 7 ), que trunca el resultado.
El domingo adicional para el resto de 1 a 6 días depende del primer día del intervalo. Si es domingo, bingo; si es un lunes, que mal. Etc. Podemos derivar una fórmula simple de esto:
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;
Funciona para cualquier intervalo dado.
Nota:isodow
, no dow
para EXTRACT()
.
Para incluir el límite superior, simplemente reemplace z - a
con (z - a) + 1
. (Funcionaría sin paréntesis, debido a la precedencia del operador, pero es mejor que quede claro).
La característica de rendimiento es O(1) (constante) en oposición a un agregado condicional sobre un conjunto generado con O(N) .
Relacionado:
- ¿Cómo determino el último día del mes anterior usando PostgreSQL?
- Calcular horas de trabajo entre 2 fechas en PostgreSQL