Pregunta

Tenemos una tabla que es de la forma:

ID,Value1,Value2,Value3
1,2,3,4

Tenemos que transformar esto en.

ID,Name,Value
1,'Value1',2
1,'Value2',3
1,'Value3',4

¿Hay una forma inteligente de hacer esto en una instrucción SELECT (es decir, sin sindicatos)? Los nombres de columna valor1, valor2 y Value3 son fijos y constante.

La base de datos es Oracle 9i.

¿Fue útil?

Solución

Esto funciona en Oracle 10g:

select id, 'Value' || n as name,
       case n when 1 then value1 when 2 then value2 when 3 then value3 end as value
from (select rownum n
      from (select 1 from dual connect by level <= 3)) ofs, t

Creo que Oracle 9i tenía consultas recursivas? De todos modos, estoy bastante seguro de que cuenta con el apoyo CASO, por lo que incluso si no tiene consultas recursivas, sólo puede hacer "(seleccionar 1 de unión dual all select 2 de unión dual all select 3 de dobles) OFS" en su lugar. Abusar de consultas recursivas es un poco más general- para Oracle. (El uso de uniones para generar filas es portátil a otro DB, sin embargo)

Otros consejos

Hacer un union un tiro.

select ID, 'Value1' as Name, Value1 as Value from table_name union all
select ID, 'Value2', Value2 as Value from table_name union all
select ID, 'Value3', Value3 as Value from table_name

order by ID, Name

usando union all significa que el servidor no llevará a cabo un distinct (que es implícito en las operaciones de union). No debería haber ninguna diferencia con los datos (ya que sus identificaciones deben espera que sea diferente), pero podría acelerarlo un poco.

Puede hacerlo de esta manera, pero no es bastante:

SELECT id,'Value 1' AS name,value1 AS value FROM mytable
UNION
SELECT id,'Value 2' AS name,value2 AS value FROM mytable
UNION
SELECT id,'Value 3' AS name,value3 AS value FROM mytable

unificante tres sentencias de selección debe hacer el truco:

SELECT ID, 'Value1', Value1 AS Value
FROM TABLE
UNION
SELECT ID, 'Value2', Value2 AS Value
FROM TABLE
UNION
SELECT ID, 'Value3', Value3 AS Value
FROM TABLE

Si está utilizando SQL Server 2005 +, puede utilizar UNPIVOT

CREATE TABLE #tmp ( ID int, Value1 int, Value2 int, Value3 int)

INSERT INTO #tmp (ID, Value1, Value2, Value3) VALUES (1, 2, 3, 4)

SELECT
    *
FROM
    #tmp

SELECT
    *
FROM
    #tmp
UNPIVOT
(
    [Value] FOR [Name] IN (Value1, Value2, Value3)
) uPIVOT

DROP TABLE #tmp

A UNION ALL, como otros han sugerido, es probablemente la mejor opción en SQL. También puede ser que desee considerar el manejo de este en la parte delantera dependiendo de lo que son sus necesidades específicas.

sintaxis CTE puede ser diferente para Oracle (me encontré en Teradata), pero sólo se utiliza CTE para proporcionar datos de prueba, los 1 2 3 y 4. Puede utilizar tabla temporal en su lugar. La instrucción SELECT SQL real es sencillo de vainilla y lo hará en cualquier base de datos relacional.

Para SQL Server, considere UNPIVOT como una alternativa a la unión:

SELECT id, value, colname
FROM #temp t
UNPIVOT (Value FOR ColName IN (value1,value2,value3)) as X

Esto devolverá el nombre de columna también. Estoy seguro de lo que la X se utiliza para, pero no puedo dejarlo fuera.

Prueba esto:

CTE crea una tabla temporal con 4 valores. Puede ejecutar este al igual que en cualquier base de datos.

with TEST_CTE (ID) as

(select * from (select '1' as a) as aa  union all
select * from (select '2' as b) as bb  union all
select * from (select '3' as c) as cc  union all
select * from (select '4' as d) as dd )

select a.ID, 'Value'|| a.ID, b.ID
from TEST_CTE a, TEST_CTE b
where b.ID = (select min(c.ID) from TEST_CTE c where c.ID > a.ID)

Aquí está el conjunto de resultados:

1   Value1  2

2   Value2  3

3   Value3  4

Disfrute!

Algunas ideas de último momento.

^^^ CTE sintaxis puede ser diferente en Oracle. Sólo pude ejecutarlo en Teradata. Se puede sustituir con tabla temporal o fijar la sintaxis para hacer compatibles que Oracle. La instrucción de selección es SQL plain vanilla que funcionará en cualquier base de datos.

^^^ Otra cosa a tener en cuenta. Si el campo ID es numérico, puede que tenga que echó en CHAR con el fin de concatenar con "Valor".

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top