none
Ayuda con problematica para recorrer tabla y actualizar datos. RRS feed

  • Pregunta

  • Que tal amigos recurro a ustedes porque tengo la siguiente problemática, que les planteo a continuación

    1.- tengo la tabla de parametrización de algunos productos como a continuación se muestra.


    2 tengo la tabla de Mantenimiento de Productos con la siguiente estructura

    bien lo que quiero e intento hacer es que de acuerdo al criterio de Fuentes de la tabla parametrizacion poner el numero en la tabla de Mantenimiento consecutivo en el campo de fuente

    caso 1. es decir que si por ejemplo en la tabla parametrizacion el mtoprocedimientoid =1217 tiene como fuentes 4, recorrer en la tabla mantenimiento todos los registro con id mtorequerimientoid=1217 (ordenados por descuento de mayor a menor) y poner del 1 al 4 segun el order como muestro en la tabla de arriba y en color negrito.

    caso 2 para el caso del registro con id mtorequerimientoid=385 que en parametrizacion tiene 3 fuentes y en la tabla manteminiento solo hay 2 unicamente marcar esos 2.

    lo estoy tratando de hacer con un cursor pero la verdad soy nuevo en  cursores el codigo que llevo hasta ahora el el siguiente.

    declare CursorMenorOferta Cursor for     
    
    SELECT mtoProcedimientoId, mtoRequerimientoId,descuentoOfertado
    FROM     dbo.TMP_PREFALLO
    GROUP BY mtoProcedimientoId, mtoRequerimientoId
    
    open CursorMenorOferta 
    
      FETCH CursorMenorOferta into @wprocedimientoid, @wrequerimientoid,@fuentesAsignacion,@wdescuento
    
      begin TRANSACTION
    	begin try
    		while @@FETCH_STATUS=0
    		begin
    						
    		 SELECT @fuentesAsignacion=fuentes from Productos where mtoRequerimientoId=@wrequerimientoid
    		 SELECT @ofertasCumplen = @ofertasCumplen from TMP_PREFALLO where mtoRequerimientoId=@wrequerimientoid
    
    		if(@fuentesAsignacion=1)
    		begin
    		
    			With Fuente1(MtorequerimientoId, Descuento,PrecioNeto,lugarLic) As
    				 (
    					select mtoRequerimientoId,Max(descuentoOfertado) as Descuento,Min(precioOfertado) Precio,lugarLic from TMP_PREFALLO	
    					group by mtoRequerimientoId,lugarLic
    					having lugarLic>0 and mtoRequerimientoId=@wrequerimientoid
    				 )
    				 UPDATE r SET r.asignacion = 1
    				 FROM TMP_PREFALLO  r JOIN Fuente1 t ON t.MtorequerimientoId = r.MtoRequerimientoId and r.precioNeto=t.PrecioNeto
    	
    		end		
    				
    		-- Avanzamos otro registro 
    		FETCH CursorMenorOferta into @wprocedimientoid, @wrequerimientoid,@fuentesAsignacion,@wdescuento
    		end
    
    	commit tran;
    
    	end try
    
      BEGIN CATCH
    
    	/* Hay un error, deshacemos los cambios*/ 
    
    	ROLLBACK TRANSACTION -- O solo ROLLBACK
    
    	PRINT 'Se ha producido un error!'
    
    	END CATCH
    
    
    close CursorMenorOferta 
    deallocate CursorMenorOferta

    Pero no he podido solucionarlo, podrian echarme una mano por favor muchas gracias


    Horacio Xochitemol Bautista


    • Editado Xochitemol sábado, 27 de octubre de 2018 5:22 Actualizacion
    sábado, 27 de octubre de 2018 5:21

Todas las respuestas

  • Hola Xochitemol:

    Si mal no lo he entendido, no tienes porque hacer un cursor. Puedes hacer algo como esto.

    create table requerimientos (MtoRequerimientoId int, descripcion varchar(100), fuentes int)
    go
    insert into requerimientos (MtoRequerimientoId, descripcion, fuentes) 
    values 
    (381,'CEPILLOS',1),
    (382,'CEPILLOS P',2),
    (383,'CINTAS PAR',3),
    (384,'CINTAS PAR',4),
    (385,'CINTAS MET',5)
    GO
    CREATE TABLE MOVPRODUCTOS (MtoOfertaId int, MtoRequerimientoId int, Dto float, Fuente int)
    go
    insert into MOVPRODUCTOS (MtoOfertaId, MtoRequerimientoId, Dto, Fuente)
    values
    (1206, 381, 0.15, 1),
    (1207, 381, 0.16, null),
    (1208, 381, 0.17, null),
    (1209, 382, 0.9, 1),
    (1210, 382, 0.08, 2),
    (1213, 383, 20, 1),
    (1212, 383, 0.5, 2),
    (1211, 383, 0.08, 3),
    (1214, 384, 19, 1),
    (1218, 384, 18.2, 2),
    (1216, 384, 18, 3),
    (1217, 384, 17.36, 4),
    (1215, 384, 15.6, null),
    (1220, 385, 13.43, 1),
    (1219, 385, 12, 2)
    go
    
    ;WITH cte
         AS (
         SELECT ROW_NUMBER() OVER(PARTITION BY mtoRequerimientoid ORDER BY dto DESC) AS fila,
                mtoRequerimientoid,
                mtoofertaid,
                dto,
                fuente
         FROM MOVPRODUCTOS)
         SELECT c.*,
                r.*,
                CASE
                    WHEN r.fuentes >= c.fila
                    THEN c.fila
                    ELSE null
                END AS solucion
         FROM cte c
              INNER JOIN requerimientos r ON c.MtoRequerimientoId = r.MtoRequerimientoId;

    la select de salida, solo te la he puesto para ver si concuerda exactamente con lo que pedías, caso de ser así, la solución del cte, sería,

    ;WITH cte
         AS (
         SELECT ROW_NUMBER() OVER(PARTITION BY mtoRequerimientoid ORDER BY dto DESC) AS fila,
                mtoRequerimientoid,
                mtoofertaid,
                dto,
                fuente
         FROM MOVPRODUCTOS)
         update c set fuente = (CASE
                    WHEN r.fuentes >= c.fila
                    THEN c.fila
                    ELSE null
                END)
    				  from  cte c 
    					 INNER JOIN requerimientos r ON c.MtoRequerimientoId = r.MtoRequerimientoId;
    	 
    Salida

    Espero te ayude

    sábado, 27 de octubre de 2018 5:55
  • que tal amigo como estas, de antemano muchas gracias la verdad esta solución es muy rápida; sin embargo esta se cumple para todas aquellas que tienen descuento, en caso de que por ejemplo existan productos con descuento 0, deberá considerar un campo que se llama PrecioNeto ordenado de la misma manera(de mayor a menor), mi pregunta es debo hacer otra consulta para aquellos campos donde el descuento sea igual a 0, o podre poner una condición donde si el descuento es mayor a cero esto.

    WITH cte
         AS (
         SELECT ROW_NUMBER() OVER(PARTITION BY mtoRequerimientoid ORDER BY dto DESC) AS fila,
                mtoRequerimientoid,
                mtoofertaid,
                dto,
                fuente
         FROM MOVPRODUCTOS)
         update c set fuente = (CASE
                    WHEN r.fuentes >= c.fila
                    THEN c.fila
                    ELSE null
                END)
    				  from  cte c 
    					 INNER JOIN requerimientos r ON c.MtoRequerimientoId = r.MtoRequerimientoId;
    	 

    y si no entonces

    WITH cte
         AS (
         SELECT ROW_NUMBER() OVER(PARTITION BY mtoRequerimientoid ORDER BY PrecioNeto DESC) AS fila,
                mtoRequerimientoid,
                mtoofertaid,
                PrecioNeto,
                fuente
         FROM MOVPRODUCTOS)
         update c set fuente = (CASE
                    WHEN r.fuentes >= c.fila
                    THEN c.fila
                    ELSE null
                END)
    				  from  cte c 
    					 INNER JOIN requerimientos r ON c.MtoRequerimientoId = r.MtoRequerimientoId;
    	 
    o como lo haria para que en la misa condicion considere los 2 criterios.
    Agradezco tus comentarios.


    Horacio Xochitemol Bautista


    • Editado Xochitemol sábado, 27 de octubre de 2018 13:08 Actualizacion
    sábado, 27 de octubre de 2018 13:07
  • Hola Xochitemol:

    No hace falta.

    Order by admite una expresión, por tanto y si lo he entendido bien, podría ser así.

    Como no tento tus datos ni tu columna, tendrás que verificarlo.

    WITH cte
         AS (
         SELECT ROW_NUMBER() OVER(PARTITION BY mtoRequerimientoid ORDER BY(CASE
                                                                               WHEN dto > 0
                                                                               THEN dto
                                                                               ELSE PRECIONETO
                                                                           END) DESC) AS fila,
                mtoRequerimientoid,
                mtoofertaid,
                dto,
                fuente
         FROM MOVPRODUCTOS)
         UPDATE c
           SET
               fuente = (CASE
                             WHEN r.fuentes >= c.fila
                             THEN c.fila
                             ELSE NULL
                         END)
         FROM cte c
              INNER JOIN requerimientos r ON c.MtoRequerimientoId = r.MtoRequerimientoId;
    	 

    Siempre que puedas, y se puede casi siempre, intenta olvidarte de los cursores.

    Suerte

    sábado, 27 de octubre de 2018 13:33
  • Amigo de verdad muchas gracias por contestar ya cheque tu codigo y ayuda mucho, pero que crees me equivoque al expresar el problema, debido a que en caso de que por ejemplo existan productos con descuento 0, deberá considerar un campo que se llama PrecioNeto ordenado(de menor).te pado

    te paso los datos de la tabla.

    CREATE TABLE MOVPRODUCTOS (MtoOfertaId int, MtoRequerimientoId int, Dto float, Fuente int,PrecioNeto Float)
    go
    insert into MOVPRODUCTOS (MtoOfertaId, MtoRequerimientoId, Dto, Fuente,PrecioNeto)
    values
    (1206, 381, 0.15, 1,15.20),
    (1207, 381, 0.16, null,1.00),
    (1208, 381, 0.17, null,5.00),
    (1209, 382, 0.9, 1,10.25),
    (1210, 382, 0.08, 2,7.00),
    (1213, 383, 20, 1,30.00),
    (1212, 383, 0.5, 2,10.25),
    (1211, 383, 0.08, 3,10.25),
    (1214, 384, 19, 1,10.25),
    (1218, 384, 18.2, 2,10.25),
    (1216, 384, 18, 3,10.25),
    (1217, 384, 17.36, 4,10.25),
    (1215, 384, 15.6, null,10.25),
    (1220, 385, 13.43, 1,10.25),
    (1219, 386, 12, 2,10.25),
    (1230, 387, 12, 0,10.25),
    (1231, 387, 12, 0,15.20),
    (1232, 387, 12, 0,10.26),
    (1233, 387, 12, 0,10.28),
    (1234, 387, 12, 0,10.45)
    go
    

    para el caso del mtorequerimientoid =386, suponiendo que fuentes sean 2, al tener descuento cero entonces debería considerar la columna de PrecioNeto, ordernado de Menor a Mayor y el resultado seria que el id 1230 seria 1 y el 1232 seria el 2.

    mucas gracia amigos


    Horacio Xochitemol Bautista

    domingo, 28 de octubre de 2018 12:57
  • Hola Xochitemol:

    En el ejemplo que has puesto, no es 386 sino 387, y además me has puesto null en la referencia a la tabla fuentes.

    No obstante, no cambia nada, solo la ordenación.

    Fijate en la resolución, y cambia cuando lo hayas analizado, la select por update.

    ;WITH cte
         AS (
         SELECT ROW_NUMBER() OVER(PARTITION BY mtoRequerimientoid ORDER BY dto desc,  precioneto asc)  AS fila,
                mtoRequerimientoid,
                mtoofertaid,
                isnull(dto,0) as dto,
                fuente, 
    			PrecioNeto
         FROM MOVPRODUCTOS)
         SELECT c.*,
                r.*,
                CASE
                    WHEN r.fuentes >= c.fila
                    THEN c.fila
                    ELSE null
                END AS solucion
         FROM cte c
              INNER JOIN requerimientos r ON c.MtoRequerimientoId = r.MtoRequerimientoId;

    Además trata los valores null, con la función isnull.

    Espero te ayude

    domingo, 28 de octubre de 2018 15:37