none
duplicar fila en base a él número que contenga un campo (sql 2000)

    Pregunta

  • hola, buenas noches... ¿como puedo hacer para que se dupliquen mis filas en base al numero contenido en un campo?, ejemplo:

     

    TABLA 1

    cantidad        descripción

    -------------/---------------

        4              vaso

     

    Resultado= se replicara 4 veces la fila insertandose en una tabla diferente, colocandose en el campo 'cantidad' el numero 1,

    de manera que si hago un count coincida con la fila original

     

     

     

    TABLA 2

    cantidad       descripción

    ------------/---------------

        1                    vaso

        1                    vaso

        1                    vaso

        1                    vaso

    espero me ayuden, saludos


    estudio en la duda...
    viernes, 23 de septiembre de 2011 1:06

Respuestas

  • Aquí tienes la variante que debes aplicar a la consulta:

    SELECT cantidad,descripcion	
    FROM Productos
    CROSS JOIN Numeros
    WHERE descripcion='vaso' --Aqui en teoria deberias establecer tu campo llave unica
    AND n<= (CASE WHEN cantidad=1 THEN cantidad-1
    			    ELSE(cantidad) 
    			END)
    
    


    Realiza las pruebas y me avisas.

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    • Marcado como respuesta miroquira viernes, 23 de septiembre de 2011 21:04
    viernes, 23 de septiembre de 2011 4:49

Todas las respuestas

  • Una consulta bien especial, mira, para soluciones de este tipo y otra cantidad interesante de casos siempre es recomendable utilizar una tabla de Numeros que sirva de apoyo para facilitar el diseño de tus consultas, la solución que te propongo requiere primero que creemos esta tabla de números , el algoritmo es basado en un modelo propuesto por Itzik Ben-Gan.

     

     

    -- Creating and Populating the Numeros Auxiliary Table
    SET NOCOUNT ON;
    IF OBJECT_ID('dbo.Numeros', 'U') IS NOT NULL
    DROP TABLE dbo.Numeros;
    CREATE TABLE dbo.Numeros(n INT NOT NULL PRIMARY KEY);
    
    
    DECLARE @max AS INT, @rc AS INT;
    --Aqui ubicas la cantidad de numeros deseados
    --en este caso lo dejaremos en 1000 filas
    SET @max = 1000; 
    SET @rc = 1;
    INSERT INTO dbo.Numeros(n) VALUES(1);
    WHILE @rc * 2 <= @max
    BEGIN
    INSERT INTO dbo.Numeros(n) SELECT n + @rc FROM dbo.Numeros;
    SET @rc = @rc * 2;
    END
    INSERT INTO dbo.Numeros(n)
    SELECT n + @rc FROM dbo.Numeros WHERE n + @rc <= @max;
    GO


     Ahora utilizaremos esta tabla para apoyarnos en la construcción de tu consulta, la lógica es simple, realizaremos un CROSS JOIN de tu tabla origen contra la tabla Numeros, y aplicaremos como condición la cantidad de filas que deseas duplicar (n).

     

    INSERT INTO TablaDestino(cantidad,descripcion)
    SELECT 1,descripcion	
    FROM TablaOrigen
    CROSS JOIN Numeros
    WHERE n<=5  --Numero de filas que se desean duplicar


    Como no pusistes las estructuras de las tablas no estan incluidas en el script, solo reemplazalos con los nombres de tus tablas.  Realiza las pruebas y nos cuentas como te fue.

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

     

     

     

    viernes, 23 de septiembre de 2011 2:48
  • hola,hice las pruebas y efectivamente duplica las filas con el valor que le ponga a 'n', si coloco 2 se duplica 2 veces por cada fila,el caso es que el valor a duplicar varia en cada fila  ¿como puedo asignar ese valor si cambia x cada fila? 

    -----------------------------------------------------------------------------------

    create table tablaorigen (cantidad int, descripcion char (15))

    INSERT INTO tablaorigen (cantidad, descripcion ) VALUES (4, 'vaso') --- aqui debería de duplicarse 4 veces

    INSERT INTO tablaorigen (cantidad, descripcion ) VALUES (1, 'plato')--- con 1 no debe de duplicarse

    INSERT INTO tablaorigen (cantidad, descripcion ) VALUES (2, 'cuchara')--- aqui debería de duplicarse 2 veces

    -----------------------------------------------------------------------------------

    : C

    Saludos

     

     

     

     

     

     


    estudio en la duda...
    viernes, 23 de septiembre de 2011 4:00
  • Aquí tienes la variante que debes aplicar a la consulta:

    SELECT cantidad,descripcion	
    FROM Productos
    CROSS JOIN Numeros
    WHERE descripcion='vaso' --Aqui en teoria deberias establecer tu campo llave unica
    AND n<= (CASE WHEN cantidad=1 THEN cantidad-1
    			    ELSE(cantidad) 
    			END)
    
    


    Realiza las pruebas y me avisas.

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    • Marcado como respuesta miroquira viernes, 23 de septiembre de 2011 21:04
    viernes, 23 de septiembre de 2011 4:49
  • Por si te interesa ampliar un poco al respecto, puedes perfectamente implementar una funcion y usar el operador APPLY para aplicar este esquema de duplicación para todas las filas que quieras en tu tabla origen.

     

    CREATE FUNCTION usfDuplica(@descripcion varchar(20))
    RETURNS TABLE
    AS
    RETURN
    SELECT cantidad,descripcion	
    FROM Productos
    CROSS JOIN Numeros
    WHERE descripcion=@descripcion
    AND n<= (CASE WHEN cantidad=1 THEN cantidad-1
    			    ELSE(cantidad) 
    			END)
    GO
       
    
       
    SELECT usfDuplica.cantidad,usfDuplica.descripcion FROM Productos 
    CROSS APPLY usfDuplica(descripcion)


    Solo debieras reemplazar en la funcion el parametro descripción por uno que representa la clave primaria de tu tabla (yo lo hice así con própositos de prueba) y con eso bastaria.  Cualquier duda con gusto te apoyamos.

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

    viernes, 23 de septiembre de 2011 5:02
  • apply no me lo reconoce sql 2000..
    estudio en la duda...
    viernes, 23 de septiembre de 2011 19:48
  • Claro, es reconocida a partir de SQL Server 2005, por eso te planteaba la primera opción y si querias ampliarlo con otra versión superior a 2000 podias aplicar APPLY, al final , Te fue útil la solución?

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

     


    viernes, 23 de septiembre de 2011 19:50
  • lei que el CROSS APPLY puede regresar múltiples registros pero no funciona en sql 2000 
    estudio en la duda...
    viernes, 23 de septiembre de 2011 19:53
  • Es correcto, APPLY (CROSS Y OUTER) representan una caracteristica implementada a partir de SQL Server 2005, generalmente se utilizan en funciones definidas por el usuario que retornan un tipo de datos table, pero tambien es viable utilizarlas en tablas derivadas.  Para mas información al respecto puede revisar el siguiente link:

    http://msdn.microsoft.com/es-es/library/ms175156(v=sql.90).aspx

    En el caso de su uso con tablas derivadas yo lo utilice en un post reciente, puedes revisarlo:

    http://social.msdn.microsoft.com/Forums/es-ES/sqlserveres/thread/4e43e5f4-a60f-42ad-a878-48db4600a7d8/#75f6844d-18f3-47db-abe7-eb5655d1b455

    Te aconsejo ir viendo la posibilidad de comenzar a trabajar tus aplicaciones con versiones superiores de SQL Server, los cambios han sido muchos y las mejoras haran tus desarrollos mas llevables, cualquier duda con gusto te podemos apoyar.

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

     

    viernes, 23 de septiembre de 2011 20:04
  • pues digamos que me diste un buen empujón....pero sigo con el problema, y es que mis tablas pueden tener hasta 300,000 registros y el valor de n es imposible que lo haga de manera manual

    gracias de cualquier forma...Saludos


    estudio en la duda...
    viernes, 23 de septiembre de 2011 20:05
  • hola, ya funciono con el codigo que me hiciste el gran favor de darme, sólo lo complemente con el case de la funcion usfDuplica

    quedando asi:

    INSERT INTO TablaDestino(cantidad,descripcion) SELECT 1,descripcion FROM TablaOrigen CROSS JOIN Numeros -----------------------------WHERE n<=2 --Numero de filas que se desean duplicar where n<= (CASE WHEN cantidad=1 THEN cantidad-1 ELSE(cantidad) END)

    y ya funciona!!!!!

     

     

    graciaaaaaassss......

     



    estudio en la duda...
    viernes, 23 de septiembre de 2011 20:19
  • coloco el codigo completo para futuras consultas, eres super!!!

     

     

    create table tablaorigen (cantidad int, descripcion char (15))

     

    INSERT INTO tablaorigen (cantidad, descripcion ) VALUES (2, 'vaso')

    INSERT INTO tablaorigen (cantidad, descripcion ) VALUES (1, 'plato')

    INSERT INTO tablaorigen (cantidad, descripcion ) VALUES (3, 'cuchara')

     

    create table tabladestino (cantidad int, descripcion char (15))

     

    truncate table tabladestino

    INSERT INTO tabladestino (cantidad, descripcion ) VALUES (1, 'jarra')

    INSERT INTO tabladestino (cantidad, descripcion ) VALUES (1, 'jarra')

    INSERT INTO tabladestino (cantidad, descripcion ) VALUES (1, 'jarra')

     

     

     

     

    -- Creating and Populating the Numeros Auxiliary Table

    SET NOCOUNT ON;

    IF OBJECT_ID('dbo.Numeros', 'U') IS NOT NULL

    DROP TABLE dbo.Numeros;

    CREATE TABLE dbo.Numeros(n INT NOT NULL PRIMARY KEY);

     

     

    DECLARE @max AS INT, @rc AS INT;

    --Aqui ubicas la cantidad de numeros deseados

    --en este caso lo dejaremos en 1000 filas

    SET @max = 1000; 

    SET @rc = 1;

    INSERT INTO dbo.Numeros(n) VALUES(1);

    WHILE @rc * 2 <= @max

    BEGIN

    INSERT INTO dbo.Numeros(n) SELECT n + @rc FROM dbo.Numeros;

    SET @rc = @rc * 2;

    END

    INSERT INTO dbo.Numeros(n)

    SELECT n + @rc FROM dbo.Numeros WHERE n + @rc <= @max;

    GO

     

     

    INSERT INTO TablaDestino(cantidad,descripcion)

    SELECT 1,descripcion

    FROM TablaOrigen

    CROSS JOIN Numeros

    where n<= (CASE WHEN cantidad=1 THEN cantidad-1 ELSE(cantidad) END)

     

    select * from tabladestino

     

     

     

     


    estudio en la duda...
    viernes, 23 de septiembre de 2011 20:23
  • Pero yo no veo inconvenientes en implementar el código que postee, puedes perfectamente prescindir del uso de APPLY y realizar un simple inner join de tu tabla Origen contra la funcion definida por el usuario :-)  , así que te planteo la solución (por asuntos de trabajo no tengo chance ahorita de probarlo), puedes hacerlo perfectamente tú.  Creo que podria ser:

    SELECT usfDuplica.cantidad,usfDuplica.descripcion 
    FROM Productos INNER JOIN usfDuplica(Productos.descripcion)
    ON Productos.CampoClave=usfDuplica.CampoClave
    
    
    

    Realiza las debidas pruebas y nos cuenta como te fue.

     


    "El talento es una disciplina tenaz y una larga paciencia"  Gustave Flaubert

     Email: info@geohernandez.com Blog: geeks.ms/blogs/ghernandez

     

    viernes, 23 de septiembre de 2011 20:27
  • Gracias Geovanny Excelente codigo funciona a perfeccion.

    sábado, 10 de noviembre de 2012 5:13