sql >> データベース >  >> RDS >> Oracle

表の水平値をOracleデータベース内の別の表の垂直値にバインドする方法

    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
    

    テストデータと出力:

    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
    

    編集 :説明

    回答では、と> ソリューションを読み取り可能なステップに分割するための句。それらをfromに移動できます それがあなたにとってより快適であるならば、メインクエリの節。とにかく:サブクエリ a テーブルの属性からデータを読み取ります 行の番号を追加するため、部門ごとに常に1から番号が付けられます。 row_number() そのために。サブクエリe 組合(すべて)はそれに応じて属性と番号を必要としました。両方のサブクエリで生成された番号は、メイン結合で使用されます: a.department=e.departmentおよびa.rn=e.rn

    代替案1 -Oracle 11gを使用している場合は、unpivot を使用できます。 。サブクエリによって生成されるものと、サブクエリが属性とどのように結合されるかを確認します 表:

    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;
    

    代替案2 -階層サブクエリジェネレータを使用(サブクエリ r )、接続方法によって実現 これは単純に1、2、3から数字を作成し、次に従業員と結合します。 caseの値として適切な属性が添付されています 句。残りは元の答えと同じように作られています。

    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
    

    3つのバージョンすべてで同じ出力が得られました。また、100k行の同様のテーブルで最初のオプションをテストし、数秒で出力を取得しました(5つの属性の場合)。すべてのソリューションをテストし、それらを理解してみてください。ピボット解除バージョンを使用できる場合は、これをお勧めします。説明の遅れや言語の間違いでごめんなさい。



    1. php/mysql-user_levelに基づいてリダイレクトするときに問題が発生します

    2. MySQLとチェック制約

    3. SQLで平方根を計算する方法

    4. MySQLの自然順