2012-04-09 17 views
7

Estaba viendo esta pregunta: Getting random value from a SQLite table y me preguntaba si se pueden duplicar registros usando SQL. Más específicamente, hay una construcción que permite transformar estos registros:¿Cómo puede SQL crear registros duplicados?

id| name| count 
--------------- 
1| Anne|  3 
2| Joe|  2 

en:

id| name 
-------- 
1| Anne 
1| Anne 
1| Anne 
2| Joe 
2| Joe 

donde el conteo de Anne y Joe registros en este último coincide con el valor count correspondiente en el antiguo conjunto de registros.

¿Se puede hacer con SQL? ¿Si es así, cómo?

EDIT:

Lucero le pregunta qué lenguaje SQL; cualquiera realmente, pero idealmente el enfoque más agnóstico sería el mejor.

otra edición:

¿Se puede hacer dentro de una única sentencia SQL en digamos SQLite?

+1

La respuesta corta es ** Sí, se puede hacer ** :) –

+0

Arrrite, actualicé mi pregunta ;-) –

+1

¿Por qué querrías? ¿Qué harías con el conjunto de datos resultante? –

Respuesta

8

Puede utilizar un "números" de mesa (que es muy práctico para diversas operaciones):

CREATE TABLE num 
(i UNSIGNED INT NOT NULL 
, PRIMARY KEY (i) 
) ; 

INSERT INTO num (i) 
VALUES 
    (1), (2), ..., (1000000) ; 

continuación:

SELECT 
    t.id, t.name 
FROM 
     tableX AS t 
    JOIN 
     num 
      ON num.i <= t."count" 

advertencia: Hay por supuesto una limitación en Este enfoque. La consulta no generará todas las filas deseadas tan pronto como tenga un valor en la columna count que exceda el valor máximo almacenado en la tabla Números. Si los valores en la columna count son ilimitados, solo una solución iterativa o recursiva (como las otras dos respuestas) puede funcionar.

+0

Ha nice join en todos los registros 'num' con' i <= count' –

+0

+1 : Buena solución que debe viajar muy bien. –

2

Esto se puede hacer usando un CTE recursiva:

;WITH CTE_Data as (
    select id=1, name='Anne',[COUNT]=3 
    union select id=2, name='Joe',[COUNT]=2 
), 
CTE_List as (
    select 
     id, 
     name, 
     ind=1 
    from CTE_Data 
    union all 
    select 
     l.id, 
     l.name, 
     ind=ind+1 
    from CTE_List l 
     join CTE_Data d on l.id = d.id 
    where 
     l.ind < d.[count] 
) 
select id,name from CTE_List 
order by id,ind 

NOTA: CTE_List es lo interesante, CTE_Data es sólo los datos de origen para la prueba.

4

¿Qué dialecto y versión SQL? Se puede hacer fácilmente con un CTE recursivo.

WITH cte AS (
    SELECT id, name, count FROM tbl 
    UNION ALL 
    SELECT id, name, count-1 FROM cte WHERE count>1 
) 
SELECT id, name FROM cte 
Cuestiones relacionadas