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

サブクエリを使用してOracleで結合除去が機能しない

    ここで2つの問題が発生していると思います。

    まず、結合の削除は、特定の特定の状況(PK-PK、PK-FKなど)でのみ機能します。 LEFT JOINができるのは一般的なことではありません 結合キー値ごとに1つの行を返し、Oracleに結合を削除させる任意の行セットに。

    第2に、Oracleが十分に進んでいて、LEFT JOINで参加を排除したとしても 結合キー値ごとに1行しか取得されないことがわかっていた場合、OracleはLEFT JOINSでの結合の削除をまだサポートしていません。 複合キーに基づいています(Oracleサポートドキュメント887553.1には、これはR12.2で提供されると記載されています)。

    検討できる回避策の1つは、各product_idの最後の行を含むビューを具体化することです。 。次に、LEFT JOIN マテリアライズドビューに。このように:

    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. OSXでのMySQLrootユーザーパスワードの設定

    2. コンボボックスアイテムを選択するときにPHPコードを実行する

    3. MySQLで時間を「2:34時間」、「0:34時間」などにフォーマットする方法

    4. mysql:特定のデータベースへの開いているすべての接続を表示しますか?