Question

Nous avons une table qui est de la forme:

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

Nous devons le transformer en.

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

Y at-il une façon intelligente de le faire dans une instruction SELECT (i.e. sans UNIONs)? Les noms de colonnes valeur1, valeur2 et valeur3 sont fixes et constantes.

La base de données est oracle 9i.

Était-ce utile?

La solution

Cela fonctionne sur 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

Je pense que Oracle 9i avait des requêtes récursives? Quoi qu'il en soit, je suis sûr qu'il a le soutien de CASE, même si elle n'a pas des requêtes récursives, vous pouvez juste faire « (sélectionner 1 de double union all select 2 de double union all select 3 de double) ofs » à la place. Abuser requêtes récursives est un peu plus général- pour Oracle. (Utiliser les syndicats pour générer des lignes est portable à d'autres blocs de données, bien que)

Autres conseils

Donnez un union un coup de feu.

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

en utilisant union all signifie que le serveur ne va pas effectuer une distinct (qui est implicite dans les opérations de union). Il ne devrait faire aucune différence avec les données (depuis vos années ID devraient être différents VA BIEN), mais il pourrait accélérer un peu.

Vous pouvez le faire comme ça, mais ce n'est pas assez:

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 trois instructions select devrait faire l'affaire:

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 vous utilisez SQL Server 2005+ vous pouvez utiliser 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

UNION ALL, comme d'autres l'ont suggéré, est probablement votre meilleur pari dans SQL. Vous pouvez également envisager la manipulation de ce à l'avant en fonction de vos besoins spécifiques.

syntaxe CTE peut être différent pour Oracle (je l'ai couru dans Teradata), mais je ne CTE utilisé pour fournir des données de test, les 1 2 3 et 4. Vous pouvez utiliser à la place table temporaire. L'instruction select est réelle SQL vanilles et il sera sur une base de données relationnelle.

Pour Sql Server, considérer UNPIVOT comme une alternative à l'union:

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

Ceci renvoie le nom de la colonne ainsi. Je ne suis pas sûr ce que le X est utilisé pour, mais vous ne peut pas faire autrement.

Essayez ceci:

CTE crée une table temporaire avec 4 valeurs. Vous pouvez exécuter cela comme est dans une base de données.

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)

Voici le jeu de résultats:

1   Value1  2

2   Value2  3

3   Value3  4

Amusez-vous!

Certains après coup.

^^^ syntaxe CTE peut être différent dans Oracle. Je ne pouvais courir dans Teradata. Vous pouvez le remplacer par table temporaire ou fixer la syntaxe pour le rendre compatible Oracle. L'instruction select est SQL vanilles qui fonctionnera sur une base de données.

^^^ Une autre chose à noter. Si le champ ID est numérique, vous devrez peut-être de le jeter dans CHAR pour concaténer avec « valeur ».

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top