sql >> Database teknologi >  >> RDS >> Oracle

Sådan bindes vandrette værdier af en tabel til vertikale værdier af en anden tabel i Oracle-databasen

with a as ( select a.*, row_number() over (partition by department order by attributeID) rn from attributes a), e as ( select employeeId, department, attribute1, 1 rn from employees union all select employeeId, department, attribute2, 2 rn from employees union all select employeeId, department, attribute3, 3 rn from employees ) select e.employeeId, a.attributeid, e.department, a.attribute, a.meaning, e.attribute1 as value from e join a on a.department=e.department and a.rn=e.rn order by e.employeeId, a.attributeid

Test data og output:

create table employees (employeeID number(3), name varchar2(10), department varchar2(5), age number(3), attribute1 varchar2(10), attribute2 varchar2(10), attribute3 varchar2(10));
insert into employees values (1, 'john', 'IT', 22, 'attr1val1', 'attr2val2',  null);
insert into employees values (2, 'jane', 'HR', 32, 'attr1val3', 'attr2val4',  'attr3val5');
insert into employees values (3, 'joe',  'HR', 23, 'attr1val6', 'attr2val7',  'attr3val8');
insert into employees values (4, 'jack', 'IT', 45, 'attr1val9', 'attr2val10', null);

create table attributes (attributeID number(3), department varchar2(10), attribute varchar2(10), meaning varchar2(10));
insert into attributes values (1, 'IT', 'attribute1', 'laptoptype');
insert into attributes values (2, 'IT', 'attribute2', 'networkloc');
insert into attributes values (3, 'HR', 'attribute1', 'location');
insert into attributes values (4, 'HR', 'attribute2', 'position');
insert into attributes values (5, 'HR', 'attribute3', 'allocation');

EMPLOYEEID ATTRIBUTEID DEPARTMENT ATTRIBUTE  MEANING    VALUE
---------- ----------- ---------- ---------- ---------- ----------
         1           1 IT         attribute1 laptoptype attr1val1
         1           2 IT         attribute2 networkloc attr2val2
         2           3 HR         attribute1 location   attr1val3
         2           4 HR         attribute2 position   attr2val4
         2           5 HR         attribute3 allocation attr3val5
         3           3 HR         attribute1 location   attr1val6
         3           4 HR         attribute2 position   attr2val7
         3           5 HR         attribute3 allocation attr3val8
         4           1 IT         attribute1 laptoptype attr1val9
         4           2 IT         attribute2 networkloc attr2val10
 

Rediger :Forklaring

Som svar brugte jeg with klausul bare for at opdele løsningen i læsbare trin. Du kan flytte dem til from klausul i hovedforespørgslen, hvis det er mere behageligt for dig. Alligevel:underforespørgsel a læser data fra tabel attributes og tilføjer nummer for rækker, så for hver afdeling er de altid nummereret fra 1. Jeg brugte rækkenummer() for det. Underforespørgsel e fagforeninger (alle) krævede attributter og numre dem i overensstemmelse hermed. Numre genereret i begge underforespørgsler bruges derefter i main join:a.department=e.department and a.rn=e.rn .

Alternativ 1 - hvis du bruger Oracle 11g, kan du bruge unpivot . Se, hvad der genereres af underforespørgsel, og hvordan det er forbundet med attributes tabel:

with e as (
    select employeeId, name, department, attribute, value from employees
      unpivot (value for attribute in ("ATTRIBUTE1", "ATTRIBUTE2", "ATTRIBUTE3"))  
  )
select e.employeeId, a.attributeid, e.department, a.attribute, 
       a.meaning, e.value 
  from e join attributes a on a.department=e.department 
                          and lower(a.attribute)=lower(e.attribute)
  order by e.employeeId, a.attributeid;
 

Alternativ 2 - med hierarkisk underforespørgselsgenerator (underforespørgsel r ), realiseret af connect by som simpelt opretter tal fra 1, 2, 3, som næste gang sættes sammen med employees og korrekte attributter er knyttet som værdi i case klausul. Resten er lavet på lignende måde som i det originale svar.

with a as (
    select a.*, row_number() over (partition by department order by attributeID) rn
      from attributes a),
  r as (select level rn from dual connect by level<=3),
  e as (
    select employeeId, department, rn,
           case when r.rn = 1 then attribute1
                when r.rn = 2 then attribute2
                when r.rn = 3 then attribute3
           end value
      from employees cross join r
  )
select e.employeeId, a.attributeid, e.department, a.attribute,
       a.meaning, e.value
  from e join a on a.department=e.department and a.rn=e.rn
  order by e.employeeId, a.attributeid
 

Alle tre versioner gav mig det samme output. Jeg testede også den første mulighed på en lignende tabel med 100k rækker og få output på få sekunder (for 5 attributter). Prøv venligst alle løsninger og prøv at forstå dem. Hvis du kan bruge unpivot version, vil jeg foretrække denne. Beklager for forsinket forklaring og eventuelle sprogfejl.



  1. Top almindelige problemer med MHA og hvordan man løser dem

  2. Meddelelse af den generelle tilgængelighed af SQL Secure 4.0

  3. hvordan man implementerer tabelarv i GreenDao

  4. Mysql:umuligt hvor bemærket efter at have læst const-tabeller