SoloCodigo

Bases de Datos => SQL Server => Mensaje iniciado por: jose# en Jueves 9 de Julio de 2009, 04:19

Título: Sugerencia Procedure Cantidad de Stock por Mes
Publicado por: jose# en Jueves 9 de Julio de 2009, 04:19
Hola amigo les comento que realizo un sitema para farmacia el caso es que realize un procedure que me permite ver la cantidad de item por mes pero para cada mes tengo un select, lo que necesito es que el procedimiento genere un solo select por ejemplo select Cod_Articulo, Cantidad_Enero, Cantidad_Febrero... si pudieran darme una sugerencia o una clausula que me pueda ayudar, de antemano muchisimas gracias.

este es el procedure y perdonen por la saturacion.

Citar

ALTER PROCEDURE [dbo].[PR_MOSTRAREGRESOSXMESDELAÑO](@FECHA DATETIME)
AS  
BEGIN
-- PARA ENERO
SELECT    dbo.ARTICULO.COD_ARTICULO as 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) AS 'Egreso Enero'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '1' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- PARA FEBRERO
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) AS 'Egreso Febrero'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '2' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- PARA MARZO
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Marzo'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '3' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- ABRIL
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Abril'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '4' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- MAYO
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Mayo'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '5' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- JUNIO
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Junio'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '6' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- JULIO
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Julio'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '7' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- AGOSTO
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Agosto'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '8' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- SEPTIEMBRE
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Septiembre'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '9' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- OCTUBRE
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Octubre'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '10' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- NOVIEMBRE
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Noviembre'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '11' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
-- DICIEMBRE
SELECT    dbo.ARTICULO.COD_ARTICULO AS 'CODIGO ITEM', dbo.ARTICULO.DESC_ARTICULO AS 'NOMBRE ITEM', dbo.ARTICULO.FORM_FARMACEUTICA AS 'FORM FARMACEUTICA', SUM(dbo.DETALLE_BOLETA.CANTIDAD) as 'Egreso Diciembre'
FROM         dbo.ARTICULO INNER JOIN
                      dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
                      WHERE MONTH(DETALLE_BOLETA.FECHA_EGRESO) = '12' AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = YEAR(@FECHA)
GROUP BY ARTICULO.COD_aRTICULO, ARTICULO.DESC_ARTICULO, ARTICULO.FORM_FARMACEUTICA ORDER BY ARTICULO.COD_aRTICULO ASC
END
Título: Re: Sugerencia Procedure Cantidad de Stock por Mes
Publicado por: Shiquilla en Lunes 13 de Julio de 2009, 12:52
Si tienes SQL Server 2005 o superior podrías mirar la sentencia PIVOT que hace lo que quieres.

Si tienes SQL Server 2000 podrías crearte una tabla temporal que contenga lo que quieres devolver y hacer una UPDATE sobre la tabla, por ejemplo:

Código: SQL
  1. DECLARE @nAño INTEGER; SET @nAño = 2005
  2. DECLARE @lnI INTEGER
  3. DECLARE @nTotal INTEGER
  4. DECLARE @sSQL VARCHAR(8000)
  5. DECLARE @dFechaINI DATETIME; SET @dFechaINI = CONVERT(DATETIME, '01/01/' + LTRIM(@nAño), 103)
  6. DECLARE @dFechaFIN DATETIME; SET @dFechaFIN = CONVERT(DATETIME, '31/12/' + LTRIM(@nAño), 103)
  7.  
  8. -- ---------------------------------------------------------------------------------------------
  9. -- Tabla de meses y años y su orden
  10. -- Es necesaria para poder realizar las updates masivas en el orden específico
  11. -- ---------------------------------------------------------------------------------------------
  12. CREATE TABLE #Dias_Meses
  13. (
  14.     nOrden NUMERIC(18,0) IDENTITY(1,1) NOT NULL,
  15.     dFecha DATETIME NOT NULL DEFAULT 0,
  16.     nMes INTEGER NOT NULL DEFAULT 0,
  17.     nAño INTEGER NOT NULL DEFAULT 0
  18.  
  19.     PRIMARY KEY (nOrden)
  20. )
  21.  
  22. -- En este caso, crea un TOP 12
  23. SET @sSQL = 'INSERT INTO #Dias_Meses (nAño) SELECT TOP ' + LTRIM(DATEDIFF(MONTH, @dFechaINI, @dFechaFIN) + 1) + ' 0 FROM SYSOBJECTS A CROSS JOIN SYSCOLUMNS B'
  24. EXEC(@sSQL)
  25.  
  26. UPDATE #Dias_Meses SET dFecha = DATEADD(MONTH, nOrden -1, '01/' + RIGHT('0' + LTRIM(MONTH(@dFechaINI)),2) + '/' + LTRIM(YEAR(@dFechaINI)))
  27. UPDATE #Dias_Meses SET nMes = MONTH(dFecha), nAño = YEAR(dFecha)
  28.  
  29. UPDATE #Dias_Meses SET dFecha = @dFechaINI WHERE nOrden = 1
  30. -- ---------------------------------------------------------------------------------------------
  31.  
  32. -- Creas la tabla con los datos fijos que vas a devolver
  33. CREATE TABLE #Datos
  34. (
  35.     sCodArticulo VARCHAR(250) NOT NULL PRIMARY KEY
  36. )
  37.  
  38. -- Añadimos las columnas necesarias a la tabla #Datos
  39. -- ---------------------------------------------------------------------------------------------
  40. SET @sSQL = ''
  41. SELECT @sSQL = @sSQL + CASE WHEN LEN(@sSQL) > 0 THEN ', ' ELSE '' END + 'nCant_' + LTRIM(nOrden) + ' NUMERIC(18,2) NOT NULL DEFAULT 0' FROM #Dias_Meses ORDER BY nOrden
  42. SET @sSQL = 'ALTER TABLE #Datos ADD ' + @sSQL
  43. PRINT @sSQL
  44. EXEC(@sSQL)
  45. -- ---------------------------------------------------------------------------------------------
  46.  
  47. -- Hace la INSERT en la tabla #Datos poniendo todos los artículos que entran en el filtro
  48. -- ---------------------------------------------------------------------------------------------
  49. INSERT INTO #Datos (sCodArticulo)
  50. SELECT dbo.ARTICULO.COD_ARTICULO
  51. FROM dbo.ARTICULO INNER JOIN dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO
  52. WHERE DETALLE_BOLETA.FECHA_EGRESO BETWEEN @dFechaINI AND @dFechaFIN
  53. GROUP BY dbo.ARTICULO.COD_ARTICULO
  54. -- ---------------------------------------------------------------------------------------------
  55.  
  56. -- Ahora, hacemos la UPDATE apoyandonos sobre la tabla #Dias_Meses
  57. -- ---------------------------------------------------------------------------------------------
  58. SET @nTotal = DATEDIFF(MONTH, @dFechaINI, @dFechaFIN) + 1
  59. SET @lnI = 1
  60. WHILE @lnI <= @nTotal
  61. BEGIN
  62.     SET @sSQL = 'UPDATE A SET A.nCant_' + LTRIM(@lnI) + ' = ISNULL(B.nTotal,0)'
  63.     SET @sSQL = @sSQL + ' FROM #Datos A'
  64.     SET @sSQL = @sSQL + ' INNER JOIN (
  65.                                         SELECT dbo.ARTICULO.COD_ARTICULO, SUM(dbo.DETALLE_BOLETA.CANTIDAD) AS nTotal
  66.                                         FROM dbo.ARTICULO INNER JOIN dbo.DETALLE_BOLETA ON dbo.ARTICULO.COD_ARTICULO = dbo.DETALLE_BOLETA.COD_ARTICULO'
  67.     SET @sSQL = @sSQL + ' INNER JOIN #Dias_Meses DM ON MONTH(DETALLE_BOLETA.FECHA_EGRESO) = DM.nMes AND YEAR(DETALLE_BOLETA.FECHA_EGRESO) = DM.nAño'
  68.     SET @sSQL = @sSQL + ' WHERE DETALLE_BOLETA.FECHA_EGRESO BETWEEN ''' + LTRIM(@dFechaINI) + ''' AND ''' + LTRIM(@dFechaFIN) + ''''
  69.     SET @sSQL = @sSQL + ' AND DM.nOrden = ' + LTRIM(@lnI)
  70.     SET @sSQL = @sSQL + ' GROUP BY dbo.ARTICULO.COD_ARTICULO) B ON A.sCodArticulo = B.COD_ARTICULO'
  71.     EXEC(@sSQL)
  72.  
  73.     SET @lnI = @lnI + 1
  74. END
  75. -- ---------------------------------------------------------------------------------------------
  76.  
  77. SELECT * FROM #Datos ORDER BY sCodArticulo
  78.  
  79. DROP TABLE #Datos
  80. DROP TABLE #Dias_Meses
  81.  

Sería hacer algo parecido, en este caso es dinámico y da igual el filtro que se haga.

Espero que te sirva, saludos.

Nota: No lo he probado
Título: Re: Sugerencia Procedure Cantidad de Stock por Mes
Publicado por: jose# en Lunes 13 de Julio de 2009, 19:03
Muchas gracias Shiquilla utilizo sql server 2005, investigue algo sobre tablas temporale y segun algunos articulos relentiza y ocupa mucha memoria, me parece mas adecuado la sentencia PIVOT francamente nunca escuche de esta sentencia pero investigarè y lo probarè te cuento luego.
Gracias...
Título: Re: Sugerencia Procedure Cantidad de Stock por Mes
Publicado por: jose# en Domingo 19 de Julio de 2009, 23:23
Lo logre esto es con pivot
Citar

SELECT ITEM,[1] ENE,[2] FEB, [3] MAR, [4] ABR,[5] MAY,[6] JUN,[7] JUL,[8] AGO,[9] SEP,[10] OCT, [11] NOV,[12] DIC
FROM (
SELECT D.COD_ARTICULO AS ITEM,A.DESC_ARTICULO AS NOMBRE, MONTH(D.FECHA_EGRESO) AS MES, D.CANTIDAD AS CANTIDAD
FROM DETALLE_BOLETA AS D INNER JOIN ARTICULO A ON D.COD_ARTICULO = A.COD_ARTICULO
  WHERE YEAR(D.FECHA_EGRESO) = '2009'
) V PIVOT (SUM(CANTIDAD) FOR MES IN([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])) AS PT


y este con Case

Citar
ç

CREATE PROCEDURE PR_REPORTE_SUMA_TOTALES (@FECHA DATETIME)
AS
BEGIN
  SELECT
 [CODIGO] = CASE WHEN ROW IS NULL THEN 'SUMA'
                     ELSE CONVERT(VARCHAR(80),[ROW]) END,
 --[NOMBRE] = ROW2,
 [ENERO] = SUM(CASE COL WHEN '1' THEN DATA ELSE 0 END ),
 [FEBRERO] = SUM(CASE COL WHEN '2' THEN DATA ELSE 0 END ),
 [MARZO] = SUM(CASE COL WHEN '3' THEN DATA ELSE 0 END ),
 [ABRIL] = SUM(CASE COL WHEN '4' THEN DATA ELSE 0 END ),
 [MAYO] = SUM(CASE COL WHEN '5' THEN DATA ELSE 0 END ),
 [JUNIO] = SUM(CASE COL WHEN '6' THEN DATA ELSE 0 END ),
 [JULIO] = SUM(CASE COL WHEN '7' THEN DATA ELSE 0 END ),
 [AGOSTO] = SUM (CASE COL WHEN '8' THEN DATA ELSE 0 END ),
 [JULIO] = SUM(CASE COL WHEN '9' THEN DATA ELSE 0 END),
 [SEPTIEMBRE] = SUM(CASE COL WHEN '10' THEN DATA ELSE 0 END),
 [NOVIEMBRE] = SUM(CASE COL WHEN '11' THEN DATA ELSE 0 END),
 [DICIEMBRE] = SUM(CASE COL WHEN '12' THEN DATA ELSE 0 END),
[TOTAL] = SUM(DATA)
FROM
  (SELECT [ROW] = (DETALLE_BOLETA.COD_ARTICULO),
  --  [ROW2] = ARTICULO.DESC_ARTICULO,
    [COL]=MONTH(FECHA_EGRESO),
    [DATA] = SUM(DETALLE_BOLETA.CANTIDAD)
   FROM DETALLE_BOLETA INNER JOIN ARTICULO
   ON (DETALLE_BOLETA.COD_ARTICULO = ARTICULO.COD_ARTICULO)
   WHERE YEAR(DETALLE_BOLETA.FECHA_EGRESO) =YEAR(@FECHA)
   GROUP BY DETALLE_BOLETA.COD_ARTICULO,MONTH(FECHA_EGRESO)
   ) F  
GROUP BY ROW WITH ROLLUP
   ORDER BY GROUPING(ROW) ASC
END


Me da totales y la suma de cada columna
Muchas gracias hasta la proxima.