none
¿Como implementar cursor en consulta SqlServer ? RRS feed

  • Pregunta

  • Hola ...

    Tengo una query en Sql Server , esta me devuelve cuatro columnas :

    'Fecha' ,  ' IdFamiliaArticulo' ,  'NombreFamiliaArticulo',   'SumImporteId'

    Algo asi:

    Fecha           IdFamiliaArticulo        NombreFamiliaArticulo       SumImporteId
    
    21/12/2020        Zapato                     Zapato                      100.00
    
    24/12/2020        Zapato                     Zapato                       300.20

    Entonces nesecito iterar (USANDO UN CURSOR) dentro de los registros devueltos para obtener una Sumatoria por cada IdFamiliaArticulo  y Mes/Año de la columna Fecha

    Algo asi:

    Mes         IdFamiliaArticulo      SumImporte
    
    2020/11       Zapatos               800.78
    
    2020/12       Zapatos               300.43
    
    2021/01       Zapatos               500.76

    La query que estoy usando es la siguiente y es a la que nesecito implementar el cursor

    SELECT  c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia, SUM(l.ImporteTotal) AS SumImporteId FROM CRMv2_000695..A_DocumentoLineaFactura l
        JOIN CRMv2_000695..A_DocumentoCabecera c ON c.IdCabecera = l.IdCabecera
        JOIN CRMv2_000695..A_Articulo a ON a.IdArticulo = l.IdArticulo
        JOIN CRMv2_000695..A_ArticuloFamilia af ON a.IdFamiliaArticulo = af.IdFamiliaArticulo
    GROUP BY c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia


    EFRAIN MEJIAS C VALENCIA - VENEZUELA


    viernes, 12 de febrero de 2021 0:10

Respuestas

  • El problema es la fecha y/o los tipos de datos.

    En mi script he declarado las variables como:

    Declare @mes varchar(6);
    Declare @idFamiliaArticulo varchar(100);
    Declare @sumImporte decimal(5,2);

    Error mio @mes = 7 caracteres y no 6. Pero @sumImporte puse decimal (5,2), y no es decimal sino money

    El id familia articulo tambíén tienes que adecuarlo. Si no sabes su tamaño o incluso por facilidad puedes poner varchar(max) o nvarchar(max) si puede contener caracteres unicode

    Nota: El concat ....varchar(max)) para que no explote ;)
    viernes, 12 de febrero de 2021 11:22

Todas las respuestas

  • Hola Efrain Mejias Castillo:

    Para poder emular tú escenario voy a utilizar una variable tipo tabla donde alimentaré los datos. 

    --- escenario
    Declare @tableOrigen table(Fecha date, idFamiliaArticulo varchar(100), NombreFamiliaArticulo varchar(100), SumImporteId decimal(5,2));
    Insert into @tableOrigen (Fecha, idFamiliaArticulo, NombreFamiliaArticulo, SumImporteId)
    values
    ('21/12/2020','Zapato','Zapato',100.00),
    ('24/12/2020','Zapato','Zapato',300.20),
    ('24/11/2020','Zapato','Zapato',300.20),
    ('01/01/2021','Zapato','Zapato',300.20);
    -- fin de escenario
    
    Declare @mes varchar(6);
    Declare @idFamiliaArticulo varchar(100);
    Declare @sumImporte decimal(5,2);
    
    Declare miCursor Cursor
    For Select 
    	Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)) as Mes, idFamiliaArticulo, sum(SumImporteId) as sumImporte
    	From @tableOrigen t --sustituir esta por su consulta original
    	group by Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)), idFamiliaArticulo;
    
    open miCursor;
    Fetch Next From miCursor into @mes, @idFamiliaArticulo, @sumImporte;
    While @@FETCH_STATUS = 0
    Begin
    
    	PRINT CONCAT( @mes,';', @idFamiliaArticulo,';',  CAST(@sumImporte AS VARCHAR(6)));
    
    Fetch Next From miCursor into @mes, @idFamiliaArticulo, @sumImporte;
    End;
    Close miCursor;
    Deallocate miCursor;

    Como no sabemos el tipo de datos de la columna fecha, ni el lenguaje de la conexión para determinar el formato de salida, la he operado como una columna tipo date, y la salida hacia un varchar.

    Cursor como se hace

    https://javifer2.wordpress.com/2020/11/28/cursor-como-se-hace/

    viernes, 12 de febrero de 2021 5:33
  • Hola ...   Javier Fernandez F

    El problema es que yo no voy a crear una tabla temporal ... yo debo iterar sobre las filas devueltas

    Si hago esto me devuelve el error : Debe declarar la variable de tabla "@miSql".

    DECLARE @miSql nvarchar(MAX);
    SET @miSql = 'SELECT c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia, SUM(l.ImporteTotal)FROM CRMv2_000695..A_DocumentoLineaFactura l
        join CRMv2_000695..A_DocumentoCabecera c ON c.IdCabecera = l.IdCabecera
        join CRMv2_000695..A_Articulo a ON a.IdArticulo = l.IdArticulo
        join CRMv2_000695..A_ArticuloFamilia af ON a.IdFamiliaArticulo = af.IdFamiliaArticulo
    GROUP BY c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia';
    
    Declare @mes varchar(6);
    Declare @idFamiliaArticulo varchar(100);
    Declare @sumImporte decimal(5,2);
    
    Declare miCursor Cursor
    For Select 
    	Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)) as Mes, idFamiliaArticulo, sum(SumImporteId) as sumImporte
    	From @miSql t --sustituir esta por su consulta original
    	group by Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)), idFamiliaArticulo;
    
    open miCursor;
    Fetch Next From miCursor into @mes, @idFamiliaArticulo, @sumImporte;
    While @@FETCH_STATUS = 0
    Begin
    
    	PRINT CONCAT( @mes,';', @idFamiliaArticulo,';',  CAST(@sumImporte AS VARCHAR(6)));
    
    Fetch Next From miCursor into @mes, @idFamiliaArticulo, @sumImporte;
    End;
    Close miCursor;
    Deallocate miCursor;


    EFRAIN MEJIAS C VALENCIA - VENEZUELA


    viernes, 12 de febrero de 2021 10:23
  • Hola Efrain:

    No tienes que iterar sobre tu consulta.

    Declare @mes varchar(6);
    Declare @idFamiliaArticulo varchar(100);
    Declare @sumImporte decimal(5,2);
    
    Declare miCursor Cursor
    For Select 
    	Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)) as Mes, idFamiliaArticulo, sum(SumImporteId) as sumImporte
    	From 
    	(
    		SELECT  c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia, SUM(l.ImporteTotal) AS SumImporteId 
    		FROM CRMv2_000695..A_DocumentoLineaFactura l
    			JOIN CRMv2_000695..A_DocumentoCabecera c ON c.IdCabecera = l.IdCabecera
    			JOIN CRMv2_000695..A_Articulo a ON a.IdArticulo = l.IdArticulo
    			JOIN CRMv2_000695..A_ArticuloFamilia af ON a.IdFamiliaArticulo = af.IdFamiliaArticulo
    		GROUP BY c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia
    
    	)
    	t 
    	group by Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)), idFamiliaArticulo;
    
    open miCursor;
    Fetch Next From miCursor into @mes, @idFamiliaArticulo, @sumImporte;
    While @@FETCH_STATUS = 0
    Begin
    
    	PRINT CONCAT( @mes,';', @idFamiliaArticulo,';',  CAST(@sumImporte AS VARCHAR(6)));
    
    Fetch Next From miCursor into @mes, @idFamiliaArticulo, @sumImporte;
    End;
    Close miCursor;
    Deallocate miCursor;

    Quizá haya algún error entre lo que devuelve mi query contra la tuya, bien sea por tipo de datos o por identificadores. (algún baile de algo).

    Valida primero esto:

     Select 
    	Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)) as Mes, idFamiliaArticulo, sum(SumImporteId) as sumImporte
    	From 
    	(
    		SELECT  c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia, SUM(l.ImporteTotal) AS SumImporteId 
    		FROM CRMv2_000695..A_DocumentoLineaFactura l
    			JOIN CRMv2_000695..A_DocumentoCabecera c ON c.IdCabecera = l.IdCabecera
    			JOIN CRMv2_000695..A_Articulo a ON a.IdArticulo = l.IdArticulo
    			JOIN CRMv2_000695..A_ArticuloFamilia af ON a.IdFamiliaArticulo = af.IdFamiliaArticulo
    		GROUP BY c.Fecha, a.IdFamiliaArticulo, af.NombreFamilia
    
    	)
    	t 
    	group by Concat(Year(t.fecha),'/', RIGHT((CONCAT('0',Month(t.fecha))),2)), idFamiliaArticulo;
    Si eso te devuelve las filas, como se requiere, luego solo alimentar el cursor con ella.

    viernes, 12 de febrero de 2021 11:00
  • Ok ...Javi Fernandez F

    pero ese print Concat No deberia salir como columnas... fijate creo q cuando es cero null  el importe explota un error

    2019/0;AM;164.16
    2019/0;AM;34.74
    2019/0;AM;159.03
    2019/0;AM;371.70
    2019/0;AM;113.34
    2019/0;AM;410.42
    2019/0;AM;210.68
    2019/1;AM;237.10
    2019/1;AM;210.36
    2019/1;AM;261.98
    2020/0;AM;233.84
    2020/0;AM;351.20
    2020/0;AM;147.80
    2020/0;AM;153.99
    2020/0;AM;196.61
    2020/1;AM;72.64
    2020/1;AM;107.70
    2021/0;AM;258.02
    Mens. 8115, Nivel 16, Estado 5, Línea 26
    Error de desbordamiento aritmético al convertir numeric al tipo de datos varchar.
    Mens. 8115, Nivel 16, Estado 8, Línea 28
    Error de desbordamiento aritmético al convertir money al tipo de datos numeric.


    EFRAIN MEJIAS C VALENCIA - VENEZUELA

    viernes, 12 de febrero de 2021 11:08
  • El problema es la fecha y/o los tipos de datos.

    En mi script he declarado las variables como:

    Declare @mes varchar(6);
    Declare @idFamiliaArticulo varchar(100);
    Declare @sumImporte decimal(5,2);

    Error mio @mes = 7 caracteres y no 6. Pero @sumImporte puse decimal (5,2), y no es decimal sino money

    El id familia articulo tambíén tienes que adecuarlo. Si no sabes su tamaño o incluso por facilidad puedes poner varchar(max) o nvarchar(max) si puede contener caracteres unicode

    Nota: El concat ....varchar(max)) para que no explote ;)
    viernes, 12 de febrero de 2021 11:22
  • Perfecto Javier Fernandez F .. muchas gracias

    Ahora te tengo otra pregunta en otro Post  :(


    EFRAIN MEJIAS C VALENCIA - VENEZUELA

    viernes, 12 de febrero de 2021 11:30