sql >> Databasteknik >  >> RDS >> Oracle

Oracle10G SQL:Förvandla kolumner till rader

Om du var på 11G kunde du använda unpivot :

SELECT subject, AVG(percentage) AS percentage
FROM (
    SELECT * FROM tablea
    UNPIVOT (percentage FOR subject IN (math, science, computer))
)
GROUP BY subject
ORDER BY subject;

SUBJECT  PERCENTAGE
-------- ----------
COMPUTER      94.33
MATH          91.33
SCIENCE       87.33

Men eftersom du inte är det kan du fejka det. Anpassning från denna webbplats :

SELECT subject, AVG(percentage) AS percentage
FROM (
    SELECT DECODE(unpivot_row, 1, 'Math',
                               2, 'Science',
                               3, 'Computer') AS subject,
           DECODE(unpivot_row, 1, math,
                               2, science,
                               3, computer) AS percentage
    FROM tablea
    CROSS JOIN (SELECT level AS unpivot_row FROM dual CONNECT BY level <= 3)
)
GROUP BY subject
ORDER BY subject;

SUBJECT  PERCENTAGE
-------- ----------
Computer      94.33
Math          91.33
Science       87.33

I båda fallen, den inre select omvandlar rader till kolumner; på 10g måste du bara göra det själv. SELECT ... CONNECT BY ... genererar bara en lista med dummyvärden, och detta måste räcka för att täcka antalet kolumner du konverterar till rader (och om du verkligen har 1000 bör du verkligen gå igenom datamodellen igen). De två decode satser använder det genererade numret för att matcha ett kolumnnamn och ett värde – kör den inre markeringen på egen hand för att se hur det ser ut.

Utan att tillgripa dynamisk SQL kan du inte komma ifrån att behöva lista kolumnerna - bara en gång med den riktiga unpivot , men två gånger med den falska 10g-versionen, och du måste se till att de matchar ordentligt och att radnummergeneratorn producerar tillräckligt med värden. (För många och du kan få udda resultat, men eftersom alla extra värden kommer att vara null här och du använder avg , det spelar inte så stor roll i det här fallet; bara som en förnuftskontroll bör du nog få den att matcha exakt ändå).

Eller en annan version, baserat på att du alltid vill ha alla kolumner utom name , vilket innebär att du bara behöver lista de kolumner du vill ha en gång och det är lättare att matcha dem visuellt - fortsätt bara att lägga till when klausuler; och du behöver inte radantalet:

SELECT subject, AVG(percentage) AS percentage
FROM (
    SELECT column_name AS subject,
        CASE
            WHEN column_name = 'MATH' then math
            WHEN column_name = 'SCIENCE' then science
            WHEN column_name = 'COMPUTER' then computer
        END AS percentage
    FROM tablea
    CROSS JOIN (
        SELECT column_name
        FROM user_tab_columns
        WHERE table_name = 'TABLEA'
        AND column_name != 'NAME'
    )
)
GROUP BY subject
ORDER BY subject;

SUBJECT                        PERCENTAGE
------------------------------ ----------
COMPUTER                            94.33
MATH                                91.33
SCIENCE                             87.33



  1. Hur sammanfogar man många rader med samma id i sql?

  2. Ändra en primärnyckel till en sammansatt primärnyckel

  3. Utmaningen är igång! Samhällsuppmaning för att skapa den snabbaste nummerseriegeneratorn

  4. Ställ in tidszon för MYSQL NOW()