C贸mo trabajar con fechas en SQL y no morir en el intento
Aprende a manejar fechas en SQL como un profesional y ten la seguridad de construir consultas seguras y precisas 馃コ

El trabajar con fechas cuando de bases de datos se trata puede dar lugar a un dolor de cabeza si no se tiene en cuenta ciertos aspectos. Por eso en esta entrada te ense帽ar茅 c贸mo debes hacer tus consultas al trabajar con fechas en el lenguaje de consulta SQL. Arrancamos!

Formato Datetime ANSI SQL

Lo primero que debes saber es qu茅 es el formato ANSI para el manejo de fechas en SQL, y se trata de un est谩ndar que especifica c贸mo se deben representar los caracteres de los valores de fecha y tiempo.

Este est谩ndar va de a帽o a segundo y tiene la siguiente apariencia:

YYYY-MM-DD HH:MM:SS

Tambi茅n se puede obviar los guiones en el a帽o, mes y d铆a quedando YYYYMMDD

Si quieres m谩s informaci贸n de este est谩ndar plasmado en la web de IBM puedes leerla aqu铆.

Este formato es el que debemos utilizar para hacer nuestras consultas SQL, esto quiere decir que si por ejemplo queremos obtener todas las 贸rdenes de venta iguales o posteriores al 5 de enero del 2023, tendr铆amos que hacer una consulta de la siguiente forma:

SELECT * FROM Orders where OrderDate >= '20230105'

Esto quiere decir que evitemos utilizar formatos regionales DDMMYYYY o MMDDYYYY ya sea con guiones o con slash como por ejemplo:

05-01-2023

01-05-2023

05/01/2023

01/05/2023

Porque si hacemos esto estamos a merced de la configuraci贸n regional que tenga el motor de la base de datos e inclusive del host pudiendo confundir un 5 de enero con un primero de mayo, esto ser铆a fatal 馃檭.

ATENCI脫N! 馃槺

Existe una trampa cuando de fechas se trata y es que si en nuestra base de datos tenemos datos que incluyen segundos, cuando queremos obtener los registros de un d铆a en particular, no basta con hacer uso del formato ANSI:

SELECT * FROM Orders WHERE OrderDate = '20230105'

Tenemos que hacer algo m谩s, y esto te lo explico en la secci贸n de abajo as铆 que contin煤a leyendo馃槈

Foto de Manasvita S en Unsplash

Hagamos consultas con SQL

Ahora vamos a SSMS y vamos a hacer algunas pruebas.

Ya que manejamos conocimientos de SQL entonces vamos a ejecutar algunas consultas, crearemos nuestra base de datos, luego nuestra tabla de ejemplo y la llenaremos con mucha data con fechas y al final haremos un peque帽o taller con consultas que involucran fechas.

Est谩 muy de moda aprender a hacer consultas de este tipo, tras el boom de la inteligencia de negocios o BI as铆 que aprovecha este art铆culo 馃

  • Creamos una base de datos
USE MASTER
CREATE DATABASE DATETEST
USE DATETEST

  • Creamos una tabla
CREATE TABLE Orders(
	Id int primary key identity,
	OrderDate datetime,
	SubTotal decimal(10,2)
)

  • Llenamos la tabla con datos
DECLARE @TMP TABLE(
	OrderDate DATETIME,
	SubTotal DECIMAL(10,2)
)

declare @counter int = 1

while(@counter <= 10000)
begin
	INSERT INTO @TMP VALUES(
		  DATEADD(SECOND, ABS(CHECKSUM(NEWID())) % 946080000 , '1990-01-01')
			, CONVERT(DECIMAL(10,2), RAND()*1000)
	)

	SET @counter = @counter + 1
end

INSERT INTO Orders
select * from @TMP
order by orderdate

Para llenar a la tabla con datos hemos hecho uso de algunos conceptos intermedio-avanzados de SQL, que ser铆a conveniente que los aprendas, sin embargo te comento brevemente qu茅 hice:

Declar茅 una tabla como variable y luego hice uso de la iteraci贸n en SQL mediante la cl谩usula WHILE.

Hice 10 mil iteraciones y en cada una insert茅 un registro a la variable de tipo tabla llamado TMP

Insert茅 orderdates random entre 1990 y 2019 y subtotales random.

Orden茅 esos registros por fecha y los insert茅 a la tabla Orders.

Ahora tienes tu tabla llena de datos para que hagas las consultas a continuaci贸n y experimentes y compruebes por ti mismo lo que este art铆culo te ense帽a 馃槈

  • Hacemos consultas diversas

Vamos a obtener las ventas para diferentes lapsos de tiempo, desde varios a帽os hasta un d铆a en particular.

--1:VENTAS DE LOS ULTIMOS 5 A脩OS
DECLARE @TMP TABLE (anio int)
declare @currentyear INT = (select year(GETDATE()))
declare @counter int = 0

while(@counter < 5)
begin
	INSERT INTO @TMP VALUES(@currentyear - @counter)

	set @counter = @counter + 1
end

SELECT * FROM Orders
WHERE YEAR(OrderDate) in (select anio from @TMP)

--2:VENTAS DEL A脩O 2015
SELECT * FROM Orders
WHERE YEAR(OrderDate) = 2015

--3:VENTAS DEL PRIMER TRIMESTRE 2015 (Q1 2015)
SELECT * FROM Orders
where YEAR(OrderDate) = 2015
and MONTH(OrderDate) IN (1,2,3)

--4:VENTAS DE ENERO 2015
SELECT * FROM Orders
where YEAR(OrderDate) = 2015
and MONTH(OrderDate) = 1

--5:VENTAS HECHAS ENTRE 11 JULIO 1997 Y EL 19 ABRIL 1998
SELECT * FROM Orders
where OrderDate between '19970711' and DATEADD(SECOND,-1, DATEADD(day,1,'19980419'))

SELECT * FROM Orders
where OrderDate >= '19970711'
and OrderDate < '19980420'

--6:VENTAS DEL 21 DE ENERO DE 1990
SELECT * FROM Orders
where OrderDate >= '19900121' and OrderDate < (DATEADD(DAY,1,'19900121'))

Me gustar铆a ahora comentarte dos cosas muy importantes.

Presta atenci贸n a las consulta 5

Nota que hay dos formas de hacerla, yo recomendar铆a la segunda.

El motivo es que si usas la cl谩usula BETWEEN tienes que tener en cuenta que obtiene todos los registros que hay entre dos fechas, incluyendo los extremos, y tiene en cuenta hasta los segundos.

As铆 que si quieres utilizar BETWEEN debes manejar muy bien esto de los segundos, y es por eso que en el extremo superior primero le a帽ado un d铆a al extremo superior, y despu茅s le resto 1 segundo para que me abarque hasta el 煤ltimo segundo del d铆a anterior que viene a ser mi rango superior mismo.

Ahora presta atenci贸n a la consulta 6:

Pasa algo similar, si tus registros tienen segundos y quieres obtener las ventas de un d铆a en particular no basta con hacer:

select * from orders where orderdate = '19900121'

ya que s贸lo te traer谩 los registros del 21 de enero de 1990 a las 0 horas 0 minutos y 0 segundos.

Sino que tendr谩s que aplicar el artificio descrito l铆neas arriba 馃槈

Y bueno eso es lo que quiero compartir con ustedes estimados devs. Es un tema que desde hace mucho he manejado en distintas oportunidades y ahora he podido plasmarlo en un art铆culo. Recuerdo que uno de los primeros blogs que le铆 sobre este tema fue hecho por Maximiliano Accotto en este art铆culo, aquella buen铆sima entrada me ayud贸 mucho en su momento y por eso quiero hoy poner mi grano de arena para todos ustedes caballeros y damas del c贸digo. 馃

Si esta entrada te ha gustado comp谩rtelo crack! 馃コ

Deja una respuesta

Tu direcci贸n de correo electr贸nico no ser谩 publicada. Los campos obligatorios est谩n marcados con *