Search code examples
sqloracle-databasejoininner-join

OR Condition in Oracle SQL


We have inherited a set of tables from a third-party product. One of the tables has 2 foreign key constraints that link to the same column on the parent table. I have simplified the tables to demonstrate this:

CREATE TABLE profile_defn 
(   
  profile_id NUMBER(10,0), 
  profile_name  VARCHAR2(50),
  CONSTRAINT pk1 PRIMARY KEY (profile_id)
);

CREATE TABLE letter_defn 
(
  letter_defn_id  NUMBER(10,0), 
  letter_name     VARCHAR2(50 BYTE), 
  orig_print_id   NUMBER(10,0),
  new_print_id    NUMBER(10,0),
  CONSTRAINT fk1 FOREIGN KEY (orig_print_id) REFERENCES profile_defn (profile_id) ENABLE,
  CONSTRAINT fk2 FOREIGN KEY (new_print_id) REFERENCES profile_defn (profile_id) ENABLE
);

INSERT INTO profile_defn
VALUES
(
  1,
  'profile1'
);

INSERT INTO profile_defn
VALUES
(
  2,
  'profile2'
);

INSERT INTO profile_defn
VALUES
(
  3,
  'profile3'
);

INSERT INTO letter_defn
VALUES 
(
  1,
  'letter1',
  1,
  2
);

INSERT INTO letter_defn
VALUES 
(
  1,
  'letter2',
  2,
  3
);

Consequently when joining the 2 tables there is an OR condition as it needs to identify matching records on either column:

SELECT * FROM letter_defn ld
JOIN profile_defn p 
ON ld.orig_print_id = p.profile_id OR ld.new_print_id = p.profile_id;

Are there are any consequences of using OR in the JOIN or is there a 'better' way of doing it?

Thanks.


Solution

  • An alternative will be to use UNION or UNION ALL which might have better execution plan :

    SELECT * FROM letter_defn ld 
    JOIN profile_defn p ON ld.orig_print_id = p.profile_id 
    UNION
    SELECT * FROM letter_defn ld 
    JOIN profile_defn p ON ld.new_print_id = p.profile_id;
    

    The consequences is that or is usually slower because the compiler can no longer perform an index seek. Other then that, it's ok .