Pergunta

Nós temos uma tabela que é da forma:

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

Precisamos transformar isso em.

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

Existe uma maneira inteligente de fazer isso em uma instrução SELECT (ou seja, sem UNIONs)? Os nomes das colunas valor1, valor2 e value3 são fixos e constante.

O banco de dados é Oracle 9i.

Foi útil?

Solução

Isso funciona em 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

Eu acho Oracle 9i teve consultas recursivas? De qualquer forma, eu tenho certeza que ele tem suporte CASE, por isso mesmo que ele não tem consultas recursivas, você pode apenas fazer "(selecione 1 de dupla união todas selecionar 2 de dupla união todas selecionar 3 de duplos) ofs" em vez. Abusando consultas recursivas é um pouco mais geral- para Oracle. (Usando sindicatos para gerar linhas é portátil para outros bancos de dados, embora)

Outras dicas

Dê um union um 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 meios union all que o servidor não irá realizar um distinct (que está implícito nas operações union). Ele não deve fazer nenhuma diferença com os dados (uma vez que os seus de ID deve esperamos ser diferente), mas pode acelerá-lo um pouco.

Você pode fazê-lo assim, mas não é bonito:

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

unioning três instruções SELECT deve fazer o truque:

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

Se você estiver usando SQL Server 2005 + então você pode usar 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 UNIÃO ALL, como já foi sugerido, é provavelmente a sua melhor aposta em SQL. Você também pode querer considerar a manusear este na extremidade dianteira, dependendo do que suas necessidades específicas são.

sintaxe CTE pode ser diferente para Oracle (eu corri em Teradata), mas eu só usei CTE para fornecer dados de teste, os 1 2 3 e 4. Você pode usar tabela temporária em vez. A instrução select real é SQL plain vanilla e vai em qualquer banco de dados relacional.

Para o SQL Server, considere UNPIVOT como uma alternativa para UNION:

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

Isso irá retornar o nome da coluna também. Tenho certeza que o X é usado para, mas você não pode deixá-lo fora.

Tente isto:

CTE cria uma tabela temporária com 4 valores. Você pode executar este como é em qualquer banco de dados.

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)

Aqui está o conjunto de resultados:

1   Value1  2

2   Value2  3

3   Value3  4

Aproveite!

Alguns afterthoughts.

^^^ sintaxe CTE pode ser diferente em Oracle. Eu só podia executá-lo em Teradata. Você pode substituí-lo com tabela temporária ou corrigir a sintaxe para torná-lo o Oracle compatível. A instrução select é SQL plain vanilla que irá funcionar em qualquer banco de dados.

^^^ Outra coisa a nota. Se o campo ID é numérico, pode ser necessário para lançá-lo em CHAR, a fim de concatenar-lo com "Valor".

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top