restar - operaciones con fechas sql
Obteniendo resultados entre dos fechas en PostgreSQL (8)
En cuanto a las fechas en las que no funciona, en las que el día es menor o igual a las 12, me pregunto si está analizando las fechas en formato AAAA-DD-MM.
Tengo la siguiente tabla:
+-----------+-----------+------------+----------+
| id | user_id | start_date | end_date |
| (integer) | (integer) | (date) | (date) |
+-----------+-----------+------------+----------+
Los campos start_date
y end_date
son valores de fecha como YYYY-MM-DD
.
Una entrada de esta tabla puede verse así: (1, 120, 2012-04-09, 2012-04-13)
.
Tengo que escribir una consulta que pueda obtener todos los resultados que coincidan con un período determinado.
El problema es que si quiero obtener los resultados del 2012-01-01
al 2012-04-12
, obtengo 0 resultados, aunque hay una entrada con start_date = "2012-04-09"
y end_date = "2012-04-13"
.
No se ofenda, pero para comprobar el rendimiento de SQL, ejecuté algunas de las soluciones pgsql mencionadas anteriormente.
Permítanme compartirles las estadísticas de los 3 mejores enfoques de solución que me encuentro.
1) Tomó: 1.58 MS Prom.
2) Tomó: 2.87 MS Prom.
3) Tomó: 3.95 MS Prom.
Ahora prueba esto:
SELECT * FROM table WHERE DATE_TRUNC(''day'', date ) >= Start Date AND DATE_TRUNC(''day'', date ) <= End Date
Ahora esta solución tomó: 1.61 Avg.
Y la mejor solución es la 1ra sugerida por
Para que una consulta funcione en cualquier configuración regional, considere formatear la fecha usted mismo:
SELECT *
FROM testbed
WHERE start_date >= to_date(''2012-01-01'',''YYYY-MM-DD'')
AND end_date <= to_date(''2012-04-13'',''YYYY-MM-DD'');
Sólo tenía la misma pregunta, y respondió de esta manera, si esto pudiera ayudar.
select *
from table
where start_date between ''2012-01-01'' and ''2012-04-13''
or end_date between ''2012-01-01'' and ''2012-04-13''
Suponiendo que desea todos los períodos de tiempo " superpuestos ", es decir, todos los que tienen al menos un día en común.
Intente visualizar períodos de tiempo en una línea de tiempo recta y muévalos alrededor de sus ojos y verá las condiciones necesarias.
SELECT *
FROM tbl
WHERE start_date <= ''2012-04-12''::date
AND end_date >= ''2012-01-01''::date;
Esto a veces es más rápido para mí que OVERLAPS
, que es la otra buena manera de hacerlo (como ya se ha proporcionado @Marco ).
Note la sutil diferencia ( por documentación ):
OVERLAPS
toma automáticamente el valor anterior del par como el inicio. Se considera que cada período de tiempo representa el intervalo medio abiertostart <= time < end
, a menos que el inicio y el final sean iguales, en cuyo caso representa ese único instante de tiempo. Esto significa, por ejemplo, que dos períodos de tiempo con solo un punto final en común no se superponen.
Énfasis en negrita el mio
Actuación
Para tablas grandes, el índice correcto puede ayudar al rendimiento ( mucho ).
CREATE INDEX tbl_date_inverse_idx ON tbl(start_date, end_date DESC);
Posiblemente con otra columna de índice (inicial) si tiene condiciones selectivas adicionales.
Tenga en cuenta el orden inverso de las dos columnas. Explicación detallada:
Tienes que usar el método de obtención de parte de fecha:
SELECT * FROM testbed WHERE start_date ::date >= to_date(''2012-09-08'' ,''YYYY-MM-DD'') and date::date <= to_date(''2012-10-09'' ,''YYYY-MM-DD'')
SELECT *
FROM mytable
WHERE (start_date, end_date) OVERLAPS (''2012-01-01''::DATE, ''2012-04-12''::DATE);
Las funciones de fecha y hora es la sección relevante en los documentos.
SELECT *
FROM ecs_table
WHERE (start_date, end_date) OVERLAPS (''2012-01-01''::DATE, ''2012-04-12''::DATE + interval ''1'');