2014-02-13 128 views
1

我想要一個自然連接2個表的選擇。將表A連接到表B,如果該表的主鍵未在表B的任何行中使用,則新臨時表C不包含表A的行。我明白爲什麼會發生這種情況,但我希望該行也可以在表C.沒有數據丟失的SQL連接

select deptno, dname, loc, count(deptno) empcount, round(avg(sal),2) avgsal 
from dept natural join emp 
group by deptno, dname, loc 

結果:

DEPTNO DNAME   LOC    EMPCOUNT  AVGSAL 
---------- -------------- ------------- ---------- ---------- 
     20 RESEARCH  DALLAS     5  2175 
     10 ACCOUNTING  NEW YORK    3 2916.67 
     30 SALES   CHICAGO    6 1566.67 

我想要什麼:

DEPTNO DNAME   LOC    EMPCOUNT  AVGSAL 
---------- -------------- ------------- ---------- ---------- 
     20 RESEARCH  DALLAS     5  2175 
     10 ACCOUNTING  NEW YORK    3 2916.67 
     30 SALES   CHICAGO    6 1566.67 
     40 OPERATIONS  BOSTON     0   0 

表部門(A):

DEPTNO DNAME   LOC   
---------- -------------- ------------- 
     10 ACCOUNTING  NEW YORK  
     20 RESEARCH  DALLAS   
     30 SALES   CHICAGO  
     40 OPERATIONS  BOSTON   

表EMP(B):

 EMPNO ENAME  JOB    MGR HIREDATE   SAL  COMM  DEPTNO 
---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 
     7369 SMITH  CLERK   7902 17-DEC-80  800     20 
     7499 ALLEN  SALESMAN  7698 20-FEB-81  1600  300   30 
     7521 WARD  SALESMAN  7698 22-FEB-81  1250  500   30 
     7566 JONES  MANAGER   7839 02-APR-81  2975     20 
     7654 MARTIN  SALESMAN  7698 28-SEP-81  1250  1400   30 
     7698 BLAKE  MANAGER   7839 01-MAY-81  2850     30 
     7782 CLARK  MANAGER   7839 09-JUN-81  2450     10 
     7788 SCOTT  ANALYST   7566 19-APR-87  3000     20 
     7839 KING  PRESIDENT   17-NOV-81  5000     10 
     7844 TURNER  SALESMAN  7698 08-SEP-81  1500   0   30 
     7876 ADAMS  CLERK   7788 23-MAY-87  1100     20 
     7900 JAMES  CLERK   7698 03-DEC-81  950     30 
     7902 FORD  ANALYST   7566 03-DEC-81  3000     20 
     7934 MILLER  CLERK   7782 23-JAN-82  1300     10 
+0

請勿使用自然連接。明確指定連接以避免未來的痛苦。 –

+0

@JeffreyKemp你說得對,我不認爲我會改變這些表上的任何東西,但是在其他項目中可能會有問題。我會改變這一點。 – Armin

回答

0

非常感謝,這是外加入我正在尋找。 所以這裏是deliveres我一直在尋找的結果SQL命令:

SQL99語法:

select deptno, dname, loc, nvl(ecount,0) empcount, nvl(round(avg(sal),2),0) avgsal 
from dept left join emp using(deptno) 
    left join (select deptno, count(deptno) ecount 
      from emp 
      group by deptno) using(deptno) 
group by deptno, dname, loc, ecount 

標準的SQL語法:

select d.deptno, d.dname, d.loc, nvl(n.ecount,0) empcount, nvl(round(avg(e.sal),2),0) avgsal 
from dept d, emp e, (select deptno, count(deptno) ecount 
        from emp 
        group by deptno) n 
where d.deptno = e.deptno (+) 
and n.deptno (+) = e.deptno 
group by d.deptno, d.dname, d.loc, n.ecount 

列empcount是0,如果有該部門沒有員工。在其他解決方案中,它是1,因爲在臨時表中的外連接之後,每個部門都有一行。

2

使用left join代替FO natural join

select deptno, dname, loc, count(deptno) empcount, round(coalesce(avg(sal), 0),2) avgsal 
from dept left join emp 
group by deptno, dname, loc 
+0

哦,是的,謝謝!使用(deptno)缺失,現在計數函數返回1,如果在部門沒有emp,因爲臨時表中有一行與左連接...任何想法如何解決這個問題? – Armin

2
select deptno, dname, loc, count(deptno) empcount, round(avg(sal),2) avgsal 
from dept 
LEFT join emp 
group by deptno, dname, loc 

這是你在看什麼呢?檢查輸出...

2

根據http://docs.oracle.com/javadb/10.8.3.0/ref/rrefsqljnaturaljoin.html你可以做一個外部自然連接,像這樣:

The following example is similar to the one above, but it also preserves 
unmatched rows from the first (left) table: 

SELECT * FROM COUNTRIES NATURAL LEFT JOIN CITIES 

所以,你會怎麼做:

select deptno, dname, loc, count(deptno) empcount, round(avg(sal),2) avgsal 
from dept natural left join emp 
group by deptno, dname, loc