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

Tham gia loại bỏ không hoạt động trong Oracle với các truy vấn phụ

Tôi nghĩ bạn có hai vấn đề đang xảy ra ở đây.

Đầu tiên, loại bỏ tham gia chỉ hoạt động đối với một số tình huống cụ thể (PK-PK, PK-FK, v.v.). Đây không phải là điều chung chung mà bạn có thể LEFT JOIN vào bất kỳ tập hợp hàng nào sẽ trả về một hàng duy nhất cho mỗi giá trị khóa tham gia và yêu cầu Oracle loại bỏ tham gia.

Thứ hai, ngay cả khi Oracle đủ nâng cao để thực hiện loại bỏ tham gia trên BẤT KỲ LEFT JOIN nào nơi nó biết rằng nó sẽ chỉ nhận được một hàng cho mỗi giá trị khóa tham gia, Oracle chưa hỗ trợ loại bỏ liên kết trên LEFT JOINS dựa trên một khóa tổng hợp (tài liệu hỗ trợ của Oracle 887553.1 cho biết điều này sẽ có trong R12.2).

Một giải pháp mà bạn có thể xem xét là thực hiện chế độ xem với hàng cuối cùng cho mỗi product_id . Sau đó, LEFT JOIN sang chế độ xem vật chất hóa. Như thế này:

create table product(
   product_id number not null
  ,constraint product_pk primary key(product_id)
);

create table product_color(
   product_id  number         not null references product
  ,color       varchar2(10)   not null
  ,constraint product_color_pk primary key(product_id)
);

create table product_price(
   product_id  number   not null references product
  ,from_date   date     not null
  ,price       number   not null
  ,constraint product_price_pk  primary key (product_id, from_date )
);

-- Add a VIRTUAL column to PRODUCT_PRICE so that we can get all the data for 
-- the latest row by taking the MAX() of this column.
alter table product_price add ( sortable_row varchar2(80) generated always as ( lpad(product_id,10,'0') || to_char(from_date,'YYYYMMDDHH24MISS') || lpad(price,10,'0'))  virtual not null );

-- Create a MV snapshot so we can materialize a view having only the latest
-- row for each product_id and can refresh that MV fast on commit.
create materialized view log on product_price with sequence, primary key, rowid ( price  ) including new values;

-- Create the MV
create materialized view product_price_latest refresh fast on commit enable query rewrite as
SELECT product_id, max( lpad(product_id,10,'0') || to_char(from_date,'YYYYMMDDHH24MISS') || lpad(price,10,'0')) sortable_row
FROM   product_price
GROUP BY product_id;

-- Create a primary key on the MV, so we can do join elimination
alter table product_price_latest add constraint ppl_pk primary key ( product_id );

-- Insert the OP's test data
insert into product values(1);
insert into product values(2);
insert into product values(3);
insert into product values(4);

insert into product_color values(1, 'Red');
insert into product_color values(2, 'Green');

insert into product_price ( product_id, from_date, price ) values(1, date '2016-01-01', 10 );
insert into product_price ( product_id, from_date, price) values(1, date '2016-02-01', 8);
insert into product_price ( product_id, from_date, price) values(1, date '2016-05-01', 5);

insert into product_price ( product_id, from_date, price) values(2, date '2016-02-01', 5);

insert into product_price ( product_id, from_date, price) values(4, date '2016-01-01', 10);

commit;

-- Create the 5NF view using the materialized view
create or replace view product_5nf as
   select p.product_id
         ,pc.color
         ,to_date(substr(ppl.sortable_row,11,14),'YYYYMMDDHH24MISS') from_date
         ,to_number(substr(ppl.sortable_row,25)) price 
     from product p
     left join product_color pc on pc.product_id = p.product_id
     left join product_price_latest ppl on ppl.product_id = p.product_id 
;

-- The plan for this should not include any of the unnecessary tables.
select product_id from product_5nf;

-- Check the plan
SELECT *
FROM   TABLE (DBMS_XPLAN.display_cursor (null, null,
                                         'ALLSTATS LAST'));

------------------------------------------------
| Id  | Operation        | Name       | E-Rows |
------------------------------------------------
|   0 | SELECT STATEMENT |            |        |
|   1 |  INDEX FULL SCAN | PRODUCT_PK |      1 |
------------------------------------------------


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. chọn N hàng trên cùng từ một bảng

  2. Ngoại lệ ORA-08103:đối tượng không còn tồn tại khi sử dụng setfetchsize của Hibernate

  3. Kích hoạt dựa trên sysdate

  4. Câu lệnh chèn nếu không tồn tại của Oracle

  5. Có thể đọc CLOB từ cơ sở dữ liệu Oracle từ xa không?