Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Cách liên kết các giá trị ngang của một bảng với các giá trị dọc của một bảng khác trong cơ sở dữ liệu 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

Dữ liệu thử nghiệm và đầu ra:

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

Chỉnh sửa :Giải thích

Trong câu trả lời, tôi đã sử dụng with mệnh đề chỉ để chia giải pháp thành các bước có thể đọc được. Bạn có thể chuyển chúng vào from mệnh đề của truy vấn chính nếu nó thoải mái hơn cho bạn. Dù sao:truy vấn con a đọc dữ liệu từ các thuộc tính attributes và thêm số cho các hàng, vì vậy đối với mỗi bộ phận, chúng luôn được đánh số từ 1. Tôi đã sử dụng row_number () cho điều đó. Truy vấn con e hợp nhất (tất cả) thuộc tính bắt buộc và số lượng tương ứng. Các số được tạo trong cả hai truy vấn phụ sau đó được sử dụng trong phép nối chính:a.department=e.department and a.rn=e.rn .

Phương án 1 - nếu bạn đang sử dụng Oracle 11g, bạn có thể sử dụng bỏ chia sẻ . Xem những gì được tạo bởi truy vấn con và cách nó được kết hợp với các thuộc tính attributes bảng:

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;

Phương án 2 - với trình tạo truy vấn con phân cấp (truy vấn con r ), được thực hiện bởi connect by đơn giản tạo các số từ 1, 2, 3 được nối tiếp với employees và thuộc tính thích hợp được đính kèm dưới dạng giá trị trong case mệnh đề. Phần còn lại được thực hiện theo cách tương tự như trong câu trả lời gốc.

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

Tất cả ba phiên bản cho tôi cùng một đầu ra. Tôi cũng đã thử nghiệm tùy chọn đầu tiên trên bảng tương tự với 100k hàng và nhận được đầu ra trong vài giây (cho 5 thuộc tính). Vui lòng kiểm tra tất cả các giải pháp và cố gắng hiểu chúng. Nếu bạn có thể sử dụng phiên bản bỏ chia sẻ, tôi muốn điều này hơn. Xin lỗi vì sự giải thích chậm trễ và bất kỳ lỗi ngôn ngữ nào.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tại sao việc kiểm tra null lại làm chậm truy vấn này?

  2. Truy vấn động PLSQL

  3. biểu thức oracle sai kiểu trong khi kiểm tra biến

  4. PL / SQL - Sử dụng biến danh sách trong mệnh đề Where In

  5. Làm thế nào để chuyển danh sách đối tượng Java sang thủ tục lưu trữ của Oracle bằng MyBatis?