如何将表的水平值绑定到oracle数据库中另一个表的垂直值

时间:2016-03-09 13:41:36

标签: oracle plsql oracle10g

我有两张桌子。

enter image description here

以属性开头的列是基于部门的更改。属性的描述在这里

enter image description here

我的要求是使用基于部门的主键获取每个属性的值,如下表所示。

enter image description here

老实说,我的程序中遇到了这个问题。我没有权限更改表格,也没有共同的唯一键列。如果有人能给我一个建议,我会很感激。

2 个答案:

答案 0 :(得分:1)

{@ 3}}已添加到Oracle 9.2中,应该可以解决问题。对于其他属性,只需添加更多子查询,其中过滤器为att.attribute =' attribute2'或者'属性3' ...

WITH e AS
(SELECT emp.employee_ID, emp.department, emp.attribute1
FROM employee emp),
a AS (SELECT att.attribute_id, att.attribute, att.meaning
FROM attribute_TYPE att
WHERE att.attribute = 'attribute1')a
SELECT e.employeeid, att.attributeid, e.department, a.attribute, 
a.meaning e.attribute1
FROM e  JOIN a ON e.department = a.department

答案 1 :(得分:1)

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

修改:解释

我在回答中使用了with 条款只是将解决方案划分为可读步骤。如果是,您可以将它们移动到主查询的from子句中 对你来说更舒服。无论如何:子查询a从表attributes读取数据并添加行数, 因此,对于每个部门,他们总是从1开始编号。我使用了row_number()。子查询e联合(所有)需要属性和数字 他们因此。然后在两个子查询中生成的数字用于主连接:a.department=e.department and a.rn=e.rn

备选方案1 - 如果您使用的是Oracle 11g,则可以使用unpivot。查看子查询生成的内容,以及它与attributes表的连接方式:

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),由connect by实现,简单地创建1,2,3的数字,然后与{{ 1}}和适当的属性 作为employees子句中的值附加。休息的方式与原始答案类似。

case

所有三个版本都给了我相同的输出。我还在100k行的类似表上测试了第一个选项,并在几秒钟内获得输出(对于5个属性)。请测试所有解决方案并尝试理解它们。如果你可以使用unpivot版本我会更喜欢这个。 很抱歉延迟解释和任何语言错误。