none
guardar en una tabla los días del mes RRS feed

  • Pregunta

  • Hola, esta vez necesito ver si me pueden ayudar a saber como se realiza esto:

    en sql, tengo que hacer algún procedimiento para que el 1 de cada mes, cargue en una tabla todos los días del mes, es decir que los guarde así:

    01/01/2013

    02/01/2012

    ...

    y así sucesivamente hasta terminar todo el mes. Mucho les agradecería me ayudaran a saber cómo se realiza este procedimiento.

    Saludos.

    Estoy trabajando con sql server 2008 r2

    jueves, 20 de diciembre de 2012 0:59

Respuestas

Todas las respuestas

  • Me temo que no hay una sentencia que te lo haga de golpe con lógica de conjuntos. Vas a tener que escribir un procedimiento con una variable y un bucle que vaya iterando y sumando un día cada vez hasta acabar el mes. Puestos a escribir un bucle de este tipo, yo lo haría con código cliente en lugar de usar un procedimiento almacenado; los lenguajes cliente suelen ser más sencillos de utilizar y mantener que el T-SQL cuando hay que hacer iteraciones o aplicar lógicas complejas. Y el rendimiento no sería un problema dado que solo hay que ejecutarlo una vez al mes y que únicamente son 31 inserciones como máximo.

    Ojo, que no digo que no lo puedas hacer con un procedimiento almacenado; al final no tendrá más de una docena de líneas. Lo que pretendía sugerir es que en estos casos, antes de lanzarse a programarlo, merece la pena dedicar un instante a meditar si es preferible meter la lógica en el cliente o en el servidor.

    jueves, 20 de diciembre de 2012 7:32
  • Bueno, al final sólo es cuestión de darle una vuelta al tema para encontrar una solución orientada a conjuntos. Ayudándonos de la tabla auxiliar de números de Itzik Ben-Gan (http://www.sqlmag.com/article/sql-server/virtual-auxiliary-table-of-numbers), el siguiente script consigue lo que necesitas:

    DECLARE @date AS DATE = '20130101'
    
    ;WITH
      L0   AS(SELECT 1 AS c UNION ALL SELECT 1),
      L1   AS(SELECT 1 AS c FROM L0 AS A CROSS JOIN L0 AS B),
      L2   AS(SELECT 1 AS c FROM L1 AS A CROSS JOIN L1 AS B),
      L3   AS(SELECT 1 AS c FROM L2 AS A CROSS JOIN L2 AS B),
      Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS n FROM L3)
    SELECT DATEADD(DAY, Nums.n, DATEADD(DAY, -1, @date))
    FROM Nums 
    WHERE Nums.n <= DATEDIFF(DAY, @date, DATEADD(MM, 1, @date))
    Luego, si necesitas ejecutarlo únicamente al inicio de cada mes, puedes meter el código dentro de un job programándolo para que se ejecute el primer día de mes y cambiando la fecha que he puesto por GETDATE()
    jueves, 20 de diciembre de 2012 9:22
  • Bueno, pues propongo una solución con un bucle:

    DECLARE @date AS DATE = '20120201'
    DECLARE @fin AS DATE = DATEADD(MM, 1, @date)
    WHILE @date<@fin
    BEGIN
        print @date
        SET @date = DATEADD(DAY, 1, @date)
    END

    No sé si será o no será más eficiente que la solución basada en lógica de conjuntos sobre la tabla Nums (probablemente sí, porque no necesita acceder a la tabla). Lo que sí que opino es que este código es bastante más fácil de entender.

    jueves, 20 de diciembre de 2012 9:58
  • La forma mas facil es teniendo una tabla calendario. Esta tabla puede ser creada para los proximos 25 - 50 años y ademas puedes adicionarle informacion sobre dias feriados, festivos, fin de semana, etc.

    Why should I consider using an auxiliary calendar table?
    http://sqlserver2000.databases.aspfaq.com/why-should-i-consider-using-an-auxiliary-calendar-table.html

    Tambien puedes usar SSAS para generar esta tabla en tu base de datos.

    Crear una dimensión de tiempo generando una tabla de tiempos
    http://msdn.microsoft.com/es-es/library/ms174832.aspx

    Una vez que tengas esta tabla, el resto seria algo como:

    insert into tu_tabla(fecha)
    select fecha
    from calendario
    where fecha >= @fecha_inicio and fecha < dateadd(month, 1, @fecha_inicio);


    AMB

    Some guidelines for posting questions...

    jueves, 20 de diciembre de 2012 14:23
  • A lo que ya te han comentado, agrego está solución también :

    DECLARE @fechaDesde AS DATE
    DECLARE @fechaHasta AS DATE
    
    SET @fechaDesde = '20120901';
    SET @fechaHasta = '20120920';
    
    	WITH x AS 
    	(
    		SELECT @fechaDesde fecha
    		UNION ALL
    		SELECT DATEADD( d , 1 ,fecha )
    		FROM x WHERE fecha < @fechaHasta
    	)
    	
    	select * from x

    SALUDOS !


    Sergio Sánchez Arias

    jueves, 20 de diciembre de 2012 14:36