You are on page 1of 9

SQL JOIN Implementations

After completing this lesson, you should be able to do the following:


1. Write SELECT statements to access data from more than one table using equality and non
equality joins.
2. View data that generally does not meet a join condition by using outer joins
3. Join a table to itself

Schema - 1 (EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)

DEPT (deptno, dname, loc))

A CROSS JOIN implements a Cartesian product, which returns rows combined from both tables. It
matches every row in one table against every row in another table. For example, if you have 3 rows in
one table and 2 rows in another youll have 2 times 3, or 6, rows in the result set.

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Cross Join Cartesian Product

Select e.empno, e.ename, e.sal, e.deptno, d.dname Select e.empno, e.ename, e.sal, e.deptno, d.dname
From emp e CROSS JOIN dept d From emp e, dept d

An INNER JOIN implements an equijoin, which returns rows combined from both tables when the
values in the join condition match. Join conditions can include one or more columns.
A NATURAL JOIN implements an equijoin, which returns rows combined from both
tables when the values in the join condition match. While the join conditions can include
one or more columns, you have no choice in selecting the join columns. A NATURAL JOIN
checks the definition of both tables (in the data catalog or metadata) and looks for like
named columns. It then joins the table based on the values of all like named columns from
both tables. One might say its an unnatural behavior because a developer has no way to
override it.

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Natural Join Equality/Simple/Equi/Normal Jon

Select empno, ename, sal, deptno, dname Select e.empno, e.ename, e.sal, e.deptno, d.dname
From emp NATURAL JOIN dept From emp e, dept d
Where e.deptno=d.deptno
Inner Join - USING Clause for composite
primary key.

Select empno, ename, sal, deptno, dname


From emp INNER JOIN dept USING(DEPTNO)

Inner Join - ON clause (INNER Join)

Select e.empno, e.ename, e.sal, e.deptno, d.dname


From emp e INNER JOIN dept d
ON e.deptno=d.deptno

Schema - 2 (EMP (empno, ename, job, mgr, hiredate, sal, comm, deptno)

DEPT (deptno, dname, loc)

LOC (loc, loc_desc, loc_cat))

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Natural Join Equality/Simple/Equi/Normal Join


For three tables. For three tables.

Select empno, sal, deptno, dname, loc, loc_desc, Select e.empno, e.ename, e.sal, d.deptno, d.dname,
loc_cat l.loc, l.loc_desc
From emp NATURAL JOIN dept NATURAL JOIN loc From emp e , dept d , loc l
Where e.deptno=d.deptno
And d.loc=l.loc
Inner Join - USING Clause
For three tables.

Select empno, sal, deptno, dname, loc, loc_cat


From emp INNER JOIN dept USING(DEPTNO)
INNER JOIN loc USING (LOC);

Inner Join - ON clause (INNER Join)


For three tables.

N/A

Schema - 3 (Table1 (col1, col2, col3, col4) -- Parent Table

Table2 (E1, E2, E3, E4, col1, col2,) -- Child Table)


ANSI Standard (Oracle 9i Onwards) Oracle Standard

Natural Join Equality/Simple/Equi/Normal Jon


For composite primary key. For composite primary key.

We cant write the natural join for Table1 and Table2 Select T1.col1, T1.col2, T1.col3, T2.E1, T2.E2, T2.E3
As Table1 has composite primary key. From Table1 T1 , Table2 T2
Where T1.col1=T2.col1
Inner Join - USING AND T1.col2=T2.col2
For composite primary key.

Select col1, col2, col3, E1, E2, E3


From Table1 INNER JOIN Table2 USING(col1, col2)

Inner Join - ON clause


For composite primary key.

Select T1.col1, T1.col2, T1.col3, T2.E1, T2.E2, T2.E3


From Table1 T1 INNER JOIN Table2 T2
ON T1.col1=T2.col1
AND T1.col2=T2.col2

A LEFT JOIN implements an equijoin and relative complement, which returns rows combined
from both tables when the values in the join condition match and the rows in the left table that arent
found in the right table. This makes a LEFT JOIN a combination of an INNER JOIN and a relative
complement of the table on the right of the join. This nuance becomes important when we examine
the (+) semantic implemented by Oracle.

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Left Outer Join - Natural Left Outer Join

Select empno, ename, sal, deptno, dname Select e.empno, e.ename, e.sal, e.deptno, d.dname
From emp NATURAL LEFT OUTER JOIN dept From emp e, dept d
Where d.deptno(+)=e.deptno
Left Outer join - USING

Select empno, ename, sal, deptno, dname


From emp LEFT OUTER JOIN dept USING(DEPTNO)

Left Outer Join - ON

Select e.empno, e.ename, e.sal, e.deptno, d.dname


From emp e LEFT OUTER JOIN dept d
ON e.deptno=d.deptno

A RIGHT JOIN implements an equijoin and relative complement, which returns rows combined
from both tables when the values in the join condition match and the rows in the right table that
arent found in the left table. This makes a RIGHT JOIN the opposite of a LEFT JOIN. Naturally, it is
also a combination of an INNER JOIN and a relative complement of the left table. Like the LEFT
JOIN, this nuance becomes important when we examine the (+) semantic implemented by Oracle.

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Right Outer Join - Natural Right Outer Join

Select empno, ename, sal, deptno, dname Select e.empno, e.ename, e.sal, e.deptno, d.dname
From emp NATURAL RIGHT OUTER JOIN dept From emp e, dept d
Where d.deptno=e.deptno(+)
Right Outer join - USING

Select empno, ename, sal, deptno, dname


From emp RIGHT OUTER JOIN dept USING(DEPTNO)

Right Outer Join - ON

Select e.empno, e.ename, e.sal, e.deptno, d.dname


From emp e RIGHT OUTER JOIN dept d
ON e.deptno=d.deptno

A FULL JOIN implements an equijoin and both relative complements, which returns rows
combined from both tables when the values in the join condition match and the rows in both the left
and right tables that arent found in their respective other tables. This makes a FULL JOIN a
combination of an INNER JOIN and relative complements of the both tables. This type of join cant
be done with the (+) alone in the older syntax. It requires left and right outer queries glued together
by a UNION set operator. The UNION set operator eliminates duplicate from the intersection of the
two tables, which are created by gluing together two outer joins.

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Full Outer Join - Natural Full Outer Join

Select empno, ename, sal, deptno, dname Select e.empno, e.ename, e.sal, e.deptno, d.dname
From emp NATURAL FULL OUTER JOIN dept From emp e, dept d
Where d.deptno(+)=e.deptno
Full Outer join - USING UNION
Select e.empno, e.ename, e.sal, e.deptno, d.dname
Select empno, ename, sal, deptno, dname From emp e, dept d
From emp FULL OUTER JOIN dept USING(DEPTNO) Where d.deptno=e.deptno(+)

Full Outer Join - ON

Select e.empno, e.ename, e.sal, e.deptno, d.dname


From emp e FULL OUTER JOIN dept d
ON e.deptno=d.deptno

*Note: In all kind of outer joins OUTER keyword is optional.

Non-equijoins:
EMPNO ENAME SAL
------Rule(s):
------- ------
7839 KING 5000
1. A non-equijoin doesnt have an equijoin statement.
2. A non-equijoin
7698 BLAKE that uses the CROSS JOIN doesnt have a join in the FROM clause.
2850
3. A non-equijoin GRADE
that uses a comma separated list LOSAL HISAL
of tables doesnt have an equijoin in the
7782 CLARK 2450 ----- ----- ------
WHERE clause.
7566 JONES 2975 1 700 1200
7654 MARTIN 1250 2 1201 1400
7499 ALLEN 1600 3 1401 2000
7844 TURNER 1500 4 Salary in the EMP
2001 table is
3000
7900 JAMES 950 5 between lo sal and hi sal in
3001 9999
... the SALGRADE table
14 rows selected.
ANSI Standard (Oracle 9i Onwards) Oracle Standard

Non Equality Join Non Equi Join

Select e.empno, e.ename, e.sal, g.grade Select e.empno, e.ename, e.sal, g.grade
From emp e CROSS JOIN salgrade g From emp e , salgrade g
WHERE e.sal BETWEEN g.losal AND g.hisal WHERE e.sal >= g.losal
AND e.sal <= g.hisal

Self Join:

Rule(s):

1. A self join is required to get the hierarchal relationship in the same table.
2. Use different aliases to the same table to perform a self join.

ANSI Standard (Oracle 9i Onwards) Oracle Standard

Self Join Self Join

Select e.ename || ' Works for ' ||m.ename Select e.ename || ' Works for ' ||m.ename
from emp e INNER JOIN emp m from emp e , emp m
ON e.mgr=m.empno where e.mgr=m.empno

SQL JOINS SCRIPT.txt


Table Structure Required for Practice Purpose:

DROP TABLE EMP;


DROP TABLE DEPT;

CREATE TABLE DEPT (DEPTNO NUMBER(2) CONSTRAINT pk_dept PRIMARY KEY,

DNAME VARCHAR2(14), LOC VARCHAR2(13) );

INSERT INTO DEPT VALUES (10, 'ACCOUNTING', 'NEW YORK');

INSERT INTO DEPT VALUES (20, 'RESEARCH', 'DALLAS');

INSERT INTO DEPT VALUES (30, 'SALES', 'CHICAGO');

INSERT INTO DEPT VALUES (40, 'OPERATIONS', 'BOSTON');

CREATE TABLE EMP

(EMPNO NUMBER(4) CONSTRAINT pk_emp PRIMARY KEY,

ENAME VARCHAR2(10), JOB VARCHAR2(9), MGR NUMBER(4),

HIREDATE DATE, SAL NUMBER(7, 2), COMM NUMBER(7, 2),

DEPTNO NUMBER(2) CONSTRAINT fk_emp_dept REFERENCES dept(deptno));

INSERT INTO EMP VALUES (7369, 'SMITH', 'CLERK', 7902, TO_DATE('17-DEC-1980', 'DD-MON-YYYY'), 800, NULL, 20);

INSERT INTO EMP VALUES (7499, 'ALLEN', 'SALESMAN', 7698, TO_DATE('20-FEB-1981', 'DD-MON-YYYY'), 1600, 300, 30);

INSERT INTO EMP VALUES (7521, 'WARD', 'SALESMAN', 7698, TO_DATE('22-FEB-1981', 'DD-MON-YYYY'), 1250, 500, 30);

INSERT INTO EMP VALUES (7566, 'JONES', 'MANAGER', 7839, TO_DATE('2-APR-1981', 'DD-MON-YYYY'), 2975, NULL, 20);

INSERT INTO EMP VALUES (7654, 'MARTIN', 'SALESMAN', 7698, TO_DATE('28-SEP-1981', 'DD-MON-YYYY'), 1250, 1400, 30);

INSERT INTO EMP VALUES (7698, 'BLAKE', 'MANAGER', 7839, TO_DATE('1-MAY-1981', 'DD-MON-YYYY'), 2850, NULL, 30);

INSERT INTO EMP VALUES (7782, 'CLARK', 'MANAGER', 7839, TO_DATE('9-JUN-1981', 'DD-MON-YYYY'), 2450, NULL, 10);

INSERT INTO EMP VALUES (7788, 'SCOTT', 'ANALYST', 7566, TO_DATE('09-DEC-1982', 'DD-MON-YYYY'), 3000, NULL, 20);

INSERT INTO EMP VALUES (7839, 'KING', 'PRESIDENT', NULL, TO_DATE('17-NOV-1981', 'DD-MON-YYYY'), 5000, NULL, 10);

INSERT INTO EMP VALUES (7844, 'TURNER', 'SALESMAN', 7698, TO_DATE('8-SEP-1981', 'DD-MON-YYYY'), 1500, 0, 30);

INSERT INTO EMP VALUES (7876, 'ADAMS', 'CLERK', 7788, TO_DATE('12-JAN-1983', 'DD-MON-YYYY'), 1100, NULL, 20);

INSERT INTO EMP VALUES (7900, 'JAMES', 'CLERK', 7698, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 950, NULL, 30);

INSERT INTO EMP VALUES (7902, 'FORD', 'ANALYST', 7566, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 3000, NULL, 20);

INSERT INTO EMP VALUES (7934, 'MILLER', 'CLERK', 7782, TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 1300, NULL, NULL);

INSERT INTO EMP VALUES (7856, 'DEEP', 'ANALYST', 7566, TO_DATE('3-DEC-1981', 'DD-MON-YYYY'), 9000, NULL, NULL);

INSERT INTO EMP VALUES (7857, 'KITE', 'CLERK', 7782, TO_DATE('23-JAN-1982', 'DD-MON-YYYY'), 5100, NULL, NULL);

COMMIT;
Drop table loc;

Create table loc (loc varchar2(10), loc_desc varchar2(10), loc_cat varchar2(10));

Alter table loc add constraint pk_loc primary key (loc);

INSERT INTO LOC VALUES ('NEW YORK', USA, C);

INSERT INTO LOC VALUES ('DALLAS', USA, C);

INSERT INTO LOC VALUES ('CHICAGO', USA, C);

INSERT INTO LOC VALUES ('BOSTON', USA, C);

INSERT INTO LOC VALUES ('DELHI', INDIA, HC);

Drop table table2;

Drop table table1;

Create table table1 (col1 number, col2 number, col3 number, col4 number);

Alter table table1 add constraint pk_table1 primary key (col1, col2);

Insert into table1 values (10, 11, 50, 100);

Insert into table1 values (11, 11, 50, 100);

Insert into table1 values (12, 11, 50, 100);

Insert into table1 values (13, 11, 50, 100);

Insert into table1 values (13, 12, 50, 100);

Create table table2 (e1 number, e2 number, e3 number, e4 number, col1 number, col2 number);

Alter table table2 add constraint pk_table2 primary key (e1);

Alter table table2 add constraint fk_pk_table1 foreign key(col1, col2) references table1(col1, col2);

Insert into table2 values (1, 2, 3, 4, 10, 11);

Insert into table2 values (2, 12,13, 14, 10, 11);

Insert into table2 values (3, 22, 23, 24, 13, 11);

Insert into table2 values (4, 32, 33, 34, 13, 12);

Insert into table2 values (5, 42, 43, 44, 10, 11);
Insert into table2 values (6, 52, 53, 54, 12, 11);

Insert into table2 values (7, 62, 36, 64, 11, 11);

Insert into table2 values (8, 72, 73, 74, 11, 11);

Insert into table2 values (9, 62, 36, 64, null, null);

Insert into table2 values (10, 72, 73, 74, null, null);

COMMIT;