0:00 0 0
Obtener el indice de dia solo desde el nombre en SQL

Obtener el indice de dia solo desde el nombre en SQL

  DrUalcman |  enero 252020

La verdad que pGetoner nombre a éste blog hoy ha sido harto complicado, ya que expresar cúal es el problema y la solución obtenida en un título sencillo, muchas veces, es imposible.

Exposición del problema

Hace unos días necesitaba hacer una consulta que, sólo conociendo el nombre del día de la semana, le pudiera agregar uno o dos días. En SQL, como en muchos lenguajes de programación, hay funciones que desde una fecha determinada te devuelve, tanto el día en número, como el día de la semana en letras, o incluso el índice del día de la semana correspondiente. Pero no tenemos ninguna función que nos devuelva eso, el índice del día sólo desde el nombre, para así, poder agregar fácilmente uno o varios días, en función de lo que estemos buscando hacer.

Tengo Miércoles y necesito saber quien viene después, Jueves, pero mientras se ejecuta una consulta con el menor código posible.

La solución propuesta

Bueno, pues aqui la solución que tras estudiar detenidamente mi problema y, como no, consultar en internet documentación y otros blogs técnicos, he desarrollado con mucho espero. Como siempre si alquien conoce una solución mejor y más eficiente, gustoso estoy de recibir los comentarios para mejorar la función y que todos disfrutemos de mejor información.

Primero necesitamos crear nuestra propia solución, por descracia SQL, como ya he comentado antes, no tiene ninguna función integrada para solucionar éste dilema. Mi solución ha sido crear dos funciones en SQL que devuelven un valos, una de ellas numérico con el índice del día de la semana, y otra que desde el índice del día de devuelva el nombre del día de la semana, por lo que devuelve un literal de texto.

Para ello tenemos que tener un poco de cuidado con el lenguaje por defecto que utilice nuestro servidor SQL, por ello, en estas funciones, pasaremos dos parámetros, el día o índice que desamos recibir y la cultura a utilizar para el idioma. Tomé esta decisión mientras escribia este blog, en la solución que untilicé, realmente no utilizo estos dos parámetros, pero creo que es interesante si trabajas con varios idiomas en la base de datos.

Pequeñas aclaraciones

Primero indicar que el ínidice de los días es como en SQL, del 1 al 7 y que como yo trabajo para una empresa con sede en Australia, los índices que propongo son en ingés, es decir, el domingo es el primer día de la semana, pero si quieres puedes cambiar el índice devuelto por la función, incluso puedes cambiar la función para detectar ésto y devolver los índices de una forma un poco más eficiente y multi idioma real. Pero no consideré necesario ésto ya que lo que nos interesa es el nombre del día de la semana y como las dos funciones están ordenadas de la misma manera nos va a dar realmente un poco igual si la semana empieza en lunes o en domingo.

Sólo nos debe de procupar cuando necesitamos controlar cual es el último día de la semana a la hora de agregar un día mas, o quitar un día, ya que si pensamos que el Domingo el el día 7 del íncide estaríamos equivocándonos con el Sábado.

Primera función GetWeekDayInt(@DayOfWeekName, @lang)

Primero comenzamos conociendo el índice del día de la seman. Para ello tenemos varias funciones en SQL para obtener el nombre del día de la semana desde una fecha concreta, pero no tenemos la fecha, por ello de esta función.

CREATE FUNCTION GetWeekDayInt 
(
@DayOfWeekName varchar(10),
@lang varchar(max)
)
RETURNS INT
AS
BEGIN
-- =============================================
-- Author:
-- Create date: <23 Ene 2020>
-- Description:
-- =============================================
DECLARE @DayWeekNumber INT = 0

if @lang = '' select @lang = 'en-EN'

IF @DayOfWeekName = format(cast('2020-01-5' as date), 'dddd', @lang) SET @DayWeekNumber = 1;
IF @DayOfWeekName = format(cast('2020-01-6' as date), 'dddd', @lang) SET @DayWeekNumber = 2;
IF @DayOfWeekName = format(cast('2020-01-7' as date), 'dddd', @lang) SET @DayWeekNumber = 3;
IF @DayOfWeekName = format(cast('2020-01-1' as date), 'dddd', @lang) SET @DayWeekNumber = 4;
IF @DayOfWeekName = format(cast('2020-01-2' as date), 'dddd', @lang) SET @DayWeekNumber = 5;
IF @DayOfWeekName = format(cast('2020-01-3' as date), 'dddd', @lang) SET @DayWeekNumber = 6;
IF @DayOfWeekName = format(cast('2020-01-4' as date), 'dddd', @lang) SET @DayWeekNumber = 7;

RETURN (@DayWeekNumber)
END

Como puedes observar estoy haciendo uso de la función FORMAT de SQL para poder enviar la cultura que quiero utilizar, y he seleccionado unas fechas ya apsadas para obtener el nombre de la día de la semana en letras.

Si no deseas enviar la cultura, ya que no lo neceitas, puede utlizar la función DATENAME(weekday, ''2020-01-05) para obtener el domingo por ejemplo.

Segunda función GetWeekDay(@IndexOfWeekDay, @lang)

Ahora la función que nos devuelve el nombre del día de la semana desde el ínidice. Esta función podría ser dependiente de la otra, es decir, enlazarlas en la misma consulta al incremente en 1 el ínidice deseado, que era lo que yo necesitaba hacer, y es en este punto dónde debemos controlar que del 7 + 1 = 1 para obtener el primer día de la semana y si estamos descontando, controlar 1-1 = 7, es un poco ilógico, pero es por no complicar mucho las funciones.

CREATE FUNCTION GetWeekDay 
(
@IndexOfWeekDay varchar(10),
@lang varchar(max)
)
RETURNS varchar(10)
AS
BEGIN
-- =============================================
-- Author:
-- Create date: <23 Ene 2020>
-- Description:
-- =============================================
DECLARE @DayOfWeekName varchar(10) = ''

if @lang = '' select @lang = 'en-EN'

IF @IndexOfWeekDay = 1 SET @DayOfWeekName = format(cast('2020-01-5' as date), 'dddd', @lang);
IF @IndexOfWeekDay = 2 SET @DayOfWeekName = format(cast('2020-01-6' as date), 'dddd', @lang);
IF @IndexOfWeekDay = 3 SET @DayOfWeekName = format(cast('2020-01-7' as date), 'dddd', @lang);
IF @IndexOfWeekDay = 4 SET @DayOfWeekName = format(cast('2020-01-1' as date), 'dddd', @lang);
IF @IndexOfWeekDay = 5 SET @DayOfWeekName = format(cast('2020-01-2' as date), 'dddd', @lang);
IF @IndexOfWeekDay = 6 SET @DayOfWeekName = format(cast('2020-01-3' as date), 'dddd', @lang);
IF @IndexOfWeekDay = 7 SET @DayOfWeekName = format(cast('2020-01-4' as date), 'dddd', @lang);

RETURN (@DayOfWeekName);
END

Ejemplo de uso

En éste trozo de código os muestro cómo utilié la consulta.

select myWeekDay, cd.IdCourier, AllDay, StartTime, CutOffTime, 
iif(dbo.getweekdayint(DeliveryDay) = 7, dbo.getweekday(1), dbo.getweekday(dbo.getweekdayint(DeliveryDay)+2)) as DeliveryDay,
(select timesel from BWN_ExpressDescriptions where timesel between 40 and 49 and description = dbo.getweekday(dbo.getweekdayint((select description from BWN_ExpressDescriptions where timesel = cd.timeselDay)) + 2)) as timeselDay,
iif(dbo.getweekdayint(NextDelivery) = 7, dbo.getweekday(1), dbo.getweekday(dbo.getweekdayint(NextDelivery)+1)) as NextDelivery,
(select timesel from BWN_ExpressDescriptions where timesel between 40 and 49 and description = dbo.getweekday(dbo.getweekdayint((select description from BWN_ExpressDescriptions where timesel = cd.timeselNext)) + 1)) as timeselNext,
0, 0, '2020/01/24', 0, 0
from couriers_days cd
inner join couriers_setup cs on cs.IdCourier = cd.IdCourier
where myWeekDay = 'Friday' and cs.Disable = 0 and cd.IdCourier in (select distinct IdCourier from couriers_days where deliveryday = 'Sunday' ) and cd.DeliveryDay = 'Sunday'
Conclusiones

Bueno y esto es todo amigos. Espero que os sirva de utilidad estas funciones, es posible que la confierta también a c# por lo que es posible que haya otro post sobre el mismo tema pero en programación.

No olvidar echar un vistazo a los mejoes links seleccionados.


Happy codding


#SQL



0 Comentarios

 
 
 

Archivo