Based on the SQLD exam syllabusReport an error
=, and a Non-EQUI join pairs them with an operator other than =, such as BETWEEN or >.(+) goes on the side that will be filled with NULL because its values run short. E.DEPTNO(+) = D.DEPTNO keeps every row of DEPT.EMP has only the department number (DEPTNO), and the department name is in DEPT. To see "employee name and department name" together, you have to pair the rows of the two tables that have the same DEPTNO. That is a join.
EMP DEPT
ENAME DEPTNO DEPTNO DNAME
CLARK 10 ───────────────────▶ 10 ACCOUNTING
KING 10 ───────────────────▶ 10 ACCOUNTING
SMITH 20 ───────────────────▶ 20 RESEARCH
... 30 SALES
40 OPERATIONS ← no matchOracle's traditional notation lists the tables in FROM separated by commas and writes the pairing condition in WHERE.
SELECT E.ENAME, E.DEPTNO, D.DNAME
FROM EMP E, DEPT D
WHERE E.DEPTNO = D.DEPTNO
AND E.DEPTNO = 10
ORDER BY E.ENAME;ENAME DEPTNO DNAME
---------- ---------- --------------
CLARK 10 ACCOUNTING
KING 10 ACCOUNTING
MILLER 10 ACCOUNTINGE and D are table aliases. In FROM, you write them after the table name with a space (you do not use AS).E.DEPTNO = D.DEPTNO) and the ordinary condition (E.DEPTNO = 10) sit together with AND.Let us count the rows of the whole join result.
SELECT COUNT(*) FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO; COUNT(*)
----------
14DEPTNO exists in both EMP and DEPT. If you do not say which table it belongs to, Oracle cannot choose.
SELECT ENAME, DEPTNO, DNAME FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO;SELECT ENAME, DEPTNO, DNAME FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO
*
ERROR at line 1:
ORA-00918: DEPTNO: column ambiguously specified - appears in DEPT and EMPIf you give an alias in FROM, the original table name can no longer be used as a prefix within that query.
SELECT EMP.ENAME FROM EMP E WHERE E.EMPNO = 7839;SELECT EMP.ENAME FROM EMP E WHERE E.EMPNO = 7839
*
ERROR at line 1:
ORA-00904: "EMP"."ENAME": invalid identifierE stands in for EMP, so a column called EMP.ENAME is considered not to exist.If you just list tables with no join condition, every row of one side is paired with every row of the other.
SELECT COUNT(*) FROM EMP, DEPT; COUNT(*)
----------
56SELECT COUNT(*) FROM EMP, SALGRADE; COUNT(*)
----------
70Even with three tables, if there is only one condition, a product arises with the remaining table.
SELECT COUNT(*) FROM EMP E, DEPT D, SALGRADE S WHERE E.DEPTNO = D.DEPTNO; COUNT(*)
----------
70The join condition does not have to be =. SALGRADE is a table that assigns a grade to each salary range (LOSAL to HISAL).
GRADE LOSAL HISAL
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999If you pair by which range an employee's salary falls into, you can attach a grade.
SELECT E.ENAME, E.SAL, S.GRADE
FROM EMP E, SALGRADE S
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL
AND E.DEPTNO = 30
ORDER BY S.GRADE, E.ENAME;ENAME SAL GRADE
---------- ---------- ----------
JAMES 950 1
MARTIN 1250 2
WARD 1250 2
ALLEN 1600 3
TURNER 1500 3
BLAKE 2850 4BETWEEN.Counting the headcount by grade means using a Non-EQUI join together with GROUP BY.
SELECT S.GRADE, COUNT(*)
FROM EMP E, SALGRADE S
WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL
GROUP BY S.GRADE
ORDER BY S.GRADE; GRADE COUNT(*)
---------- ----------
1 3
2 3
3 2
4 5
5 1<> or > can also be a join condition. With such conditions, one row is easily paired with many rows and the result grows large.
SELECT COUNT(*) FROM EMP E, DEPT D WHERE E.DEPTNO <> D.DEPTNO; COUNT(*)
----------
42By adding conditions one at a time you can keep connecting tables. Here we look at the managers' (MANAGER) names, department names, and salary grades all at once.
SELECT E.ENAME, D.DNAME, S.GRADE
FROM EMP E, DEPT D, SALGRADE S
WHERE E.DEPTNO = D.DEPTNO
AND E.SAL BETWEEN S.LOSAL AND S.HISAL
AND E.JOB = 'MANAGER'
ORDER BY E.ENAME;ENAME DNAME GRADE
---------- -------------- ----------
BLAKE SALES 4
CLARK ACCOUNTING 4
JONES RESEARCH 4E.JOB = 'MANAGER' is not a join condition but an ordinary condition that filters rows.An EQUI join throws away DEPT 40, which has no match. To keep every row of one table even without a match, you use an outer join. In Oracle's notation, you attach (+) to the column on the side that will be filled with NULL because it has no match.
SELECT D.DEPTNO, D.DNAME, E.ENAME
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
AND D.DEPTNO IN (10, 40)
ORDER BY D.DEPTNO, E.ENAME; DEPTNO DNAME ENAME
---------- -------------- ----------
10 ACCOUNTING CLARK
10 ACCOUNTING KING
10 ACCOUNTING MILLER
40 OPERATIONS(+) is attached on the EMP side, every row of DEPT is kept. Department 40 has no employee to pair with, so ENAME is NULL.(+) is a mark meaning "add a NULL row to the side that falls short". You attach it on the opposite side from the table you want to keep.| Condition | Table fully kept | Rows |
|---|---|---|
E.DEPTNO = D.DEPTNO | None (only matched rows) | 14 |
E.DEPTNO(+) = D.DEPTNO | DEPT | 15 |
E.DEPTNO = D.DEPTNO(+) | EMP | 14 |
SELECT COUNT(*) FROM EMP E, DEPT D WHERE E.DEPTNO(+) = D.DEPTNO; COUNT(*)
----------
15SELECT COUNT(*) FROM EMP E, DEPT D WHERE E.DEPTNO = D.DEPTNO(+); COUNT(*)
----------
14When you count the outer join result by department, what you count matters.
SELECT D.DEPTNO, COUNT(E.EMPNO) AS CNT, COUNT(*) AS ROWS_
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
GROUP BY D.DEPTNO
ORDER BY D.DEPTNO; DEPTNO CNT ROWS_
---------- ---------- ----------
10 3 3
20 5 5
30 6 6
40 0 1COUNT(*) counts that row and gives 1, while COUNT(E.EMPNO) leaves out NULL and gives 0. For the number of employees, COUNT(E.EMPNO) is the right one.If you leave out (+) on an ordinary condition applied to the outer-joined table, the outer join is undone.
SELECT D.DNAME, E.ENAME
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
AND E.SAL(+) > 2900
ORDER BY D.DNAME, E.ENAME;DNAME ENAME
-------------- ----------
ACCOUNTING KING
OPERATIONS
RESEARCH FORD
RESEARCH JONES
RESEARCH SCOTT
SALESSELECT D.DNAME, E.ENAME
FROM EMP E, DEPT D
WHERE E.DEPTNO(+) = D.DEPTNO
AND E.SAL > 2900
ORDER BY D.DNAME, E.ENAME;DNAME ENAME
-------------- ----------
ACCOUNTING KING
RESEARCH FORD
RESEARCH JONES
RESEARCH SCOTTE.SAL(+) > 2900: the salary condition goes into the pairing step. SALES and OPERATIONS, which have no employee matching the condition, are also kept with NULL.E.SAL > 2900: when this condition is applied to the NULL rows made by the outer join, NULL > 2900 is not true, so they drop out. The result becomes the same as an EQUI join.⚠️ Trap:
(+)can be attached on only one side. If you attach it on both sides, as inE.DEPTNO(+) = D.DEPTNO(+), you get an ORA-01468 error (a predicate may reference only one outer-joined table). A FULL OUTER JOIN, which keeps both sides, can be written only in the ANSI notation we will see tomorrow.
Tomorrow we write the same joins in the ANSI standard notation such as
JOIN ... ON, and look at the difference between ON and WHERE.
= condition. Only rows with a match on both sides remain.=, such as BETWEEN, >, or <>.(+): Oracle's outer join notation. You attach it to the column on the side that will be filled with NULL.Click a choice to reveal the answer and explanation.
Question 1
EMP has 14 rows and DEPT has 4 rows. What is the result of the following SQL? ```sql SELECT COUNT(*) FROM EMP, DEPT; ```
Question 2
SALGRADE is grade 1 for 700 to 1200, grade 2 for 1201 to 1400, grade 3 for 1401 to 2000, grade 4 for 2001 to 3000, and grade 5 for 3001 to 9999. The employees in EMP with a salary of 2001 to 3000 are JONES 2975, BLAKE 2850, CLARK 2450, SCOTT 3000, and FORD 3000. What is the result of the following SQL? ```sql SELECT COUNT(*) FROM EMP E, SALGRADE S WHERE E.SAL BETWEEN S.LOSAL AND S.HISAL AND S.GRADE = 4; ```
Question 3
Which is the correct result of running the following SQL in Oracle? ```sql SELECT ENAME, DEPTNO, DNAME FROM EMP, DEPT WHERE EMP.DEPTNO = DEPT.DEPTNO; ```
Question 4
DEPT has departments 10, 20, 30, and 40, and department 40 has no employees. All 14 people in EMP belong to one of departments 10, 20, and 30. What is the result of the following SQL? ```sql SELECT COUNT(*) FROM EMP E, DEPT D WHERE E.DEPTNO(+) = D.DEPTNO; ```
Question 5
EMP has 14 rows, DEPT has 4 rows, and SALGRADE has 5 rows. What is the result of the following SQL? ```sql SELECT COUNT(*) FROM EMP E, DEPT D, SALGRADE S WHERE E.DEPTNO = D.DEPTNO; ```