开场白,本系列非SQL入门,也就是说有些SQL相对也不是太简单;也不是SQL改写调优,也就意味着有很多SQL的执行效率可能比较低。本系列是从书上看到的一些相对感觉比较复杂的SQL的摘抄笔记。
本系列第一篇,本文的数据是自己模拟的,没有比较合理的业务逻辑,大家凑合着看吧。好了,直接上数据脚本和SQL文。
SQL中有描述的错误和不准确的地方,还请各位大神不吝指教。
另外,本系列是读书笔记,难免摘抄书中的例子,如果涉及版权问题,本人会立即删除。在这里也谢谢各位著书者。
1,子查询改为连接查询,减少表的读取次数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table emp (empno varchar2(10),ename varchar2(10),sal varchar2(10),deptno varchar2(10)); commit; insert into EMP (EMPNO, ENAME, SAL, DEPTNO) values ('E01', 'NE01', '1000', 'D01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO) values ('E02', 'NE02', '2000', 'D01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO) values ('E03', 'NE03', '3000', 'D01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO) values ('E04', 'NE04', '4000', 'D01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO) values ('E05', 'NE05', '5000', 'D02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO) values ('E06', 'NE06', '6000', 'D02'); commit; create table dept (deptno varchar2(10),dname varchar2(10)); commit; insert into DEPT (DEPTNO, DNAME) values ('D01', 'ND01'); insert into DEPT (DEPTNO, DNAME) values ('D02', 'ND02'); insert into DEPT (DEPTNO, DNAME) values ('D04', 'ND03'); insert into DEPT (DEPTNO, DNAME) values ('D04', 'ND04'); commit;
/*最简单的的子查询改为左连接。*/ SELECT E.EMPNO, E.ENAME, E.SAL, (SELECT D.DNAME FROM DEPT D WHERE D.DEPTNO = E.DEPTNO) AS DNAME FROM EMP E; SELECT E.EMPNO, E.ENAME, E.SAL, D.DNAME FROM EMP E LEFT JOIN DEPT D ON E.DEPTNO = D.DEPTNO; /*带聚合的子查询改为左连接。*/ SELECT D.DEPTNO, D.DNAME, NVL((SELECT SUM(E.SAL) FROM EMP E WHERE E.DEPTNO = D.DEPTNO), 0) AS SUM_SAL FROM DEPT D; SELECT D.DEPTNO, D.DNAME, NVL(SUM(E.SAL), 0) AS SUM_SAL FROM DEPT D LEFT JOIN EMP E ON D.DEPTNO = E.DEPTNO GROUP BY D.DEPTNO, D.DNAME;/*此处的Group By处理相对下面的处理,相对低效率*/ SELECT D.DEPTNO, D.DNAME, NVL(EE.SUM_SAL, 0) AS SUM_SAL FROM DEPT D LEFT JOIN (SELECT E.DEPTNO, SUM(E.SAL) AS SUM_SAL FROM EMP E GROUP BY E.DEPTNO) EE ON D.DEPTNO = EE.DEPTNO; /*此处先对需要关联的表进行一次聚合,在进行做链接,感觉性能开销会更小*/
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table dept (deptno varchar2(10),dname varchar2(10)); commit; insert into DEPT (DEPTNO, DNAME) values ('D01', 'ND01'); insert into DEPT (DEPTNO, DNAME) values ('D02', 'ND02'); insert into DEPT (DEPTNO, DNAME) values ('D04', 'ND03'); insert into DEPT (DEPTNO, DNAME) values ('D04', 'ND04'); commit; create table EMP ( EMPNO VARCHAR2(10), ENAME VARCHAR2(10), SAL VARCHAR2(10), DEPTNO VARCHAR2(10), SAL_DATE VARCHAR2(10) ) commit; insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E01', 'NE01', '1000', 'D01', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E02', 'NE02', '2000', 'D01', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E03', 'NE03', '3000', 'D01', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E04', 'NE04', '4000', 'D01', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E05', 'NE05', '5000', 'D02', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E06', 'NE06', '6000', 'D02', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E01', 'NE01', '2000', 'D01', '02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E02', 'NE02', '2000', 'D01', '02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E03', 'NE03', '3000', 'D01', '02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E04', 'NE04', '4000', 'D01', '02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E05', 'NE05', '5000', 'D02', '02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E06', 'NE06', '6000', 'D02', '02'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E01', 'NE01', '1000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E02', 'NE02', '4000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E03', 'NE03', '3000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E04', 'NE04', '4000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E05', 'NE05', '5000', 'D02', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E06', 'NE06', '6000', 'D02', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E01', 'NE01', '1000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E02', 'NE02', '2000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E03', 'NE03', '3000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E04', 'NE04', '4000', 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E05', 'NE05', '5000', 'D02', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('E06', 'NE06', '6000', 'D02', '03'); commit;
SELECT D.DEPTNO, D.DNAME, (SELECT SUM(E.SAL) FROM EMP E WHERE E.SAL_DATE = '01' AND E.DEPTNO = D.DEPTNO) AS SUM_SAL_01, (SELECT SUM(E.SAL) FROM EMP E WHERE E.SAL_DATE = '02' AND E.DEPTNO = D.DEPTNO) AS SUM_SAL_02, (SELECT SUM(E.SAL) FROM EMP E WHERE E.SAL_DATE = '03' AND E.DEPTNO = D.DEPTNO) AS SUM_SAL_03 FROM DEPT D; SELECT D.DEPTNO,D.DNAME,EE.SUM_SAL_01,EE.SUM_SAL_02,EE.SUM_SAL_03 FROM DEPT D LEFT JOIN (SELECT E.DEPTNO, SUM(CASE WHEN E.SAL_DATE = '01' THEN TO_NUMBER(E.SAL) ELSE 0 END) AS SUM_SAL_01, SUM(CASE WHEN E.SAL_DATE = '02' THEN TO_NUMBER(E.SAL) ELSE 0 END) AS SUM_SAL_02, SUM(CASE WHEN E.SAL_DATE = '03' THEN TO_NUMBER(E.SAL) ELSE 0 END) AS SUM_SAL_03 FROM EMP E GROUP BY E.DEPTNO) EE ON D.DEPTNO=EE.DEPTNO;
不等连接的子查询改为连接查询
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table SALDATE ( ITEM_NO VARCHAR2(10), SALE_DATE VARCHAR2(10) ); commit; insert into SALDATE (ITEM_NO, SALE_DATE) values ('001', '01'); insert into SALDATE (ITEM_NO, SALE_DATE) values ('001', '05'); insert into SALDATE (ITEM_NO, SALE_DATE) values ('001', '06'); insert into SALDATE (ITEM_NO, SALE_DATE) values ('002', '02'); insert into SALDATE (ITEM_NO, SALE_DATE) values ('002', '10'); insert into SALDATE (ITEM_NO, SALE_DATE) values ('003', '01'); insert into SALDATE (ITEM_NO, SALE_DATE) values ('003', '02'); commit; create table PRODUCT ( ITEM_NO VARCHAR2(10), ITEM_NM VARCHAR2(10), PRO_ADDRESS VARCHAR2(10), PRO_DATE VARCHAR2(10) ); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('001', 'A001', 'TOKYO', '04'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('002', 'A002', 'TOKYO', '04'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('003', 'A003', 'TOKYO', '07'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('004', 'A004', 'BEIJING', '08'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('005', 'A005', 'BEIJING', '07'); commit;
SELECT P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, (SELECT MIN(S.SALE_DATE) FROM SALDATE S WHERE S.SALE_DATE >= P.PRO_DATE AND P.ITEM_NO = S.ITEM_NO) AS MIN_SALDATE FROM PRODUCT P ORDER BY P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, MIN_SALDATE; /*构造临时表,筛选数据后用ROWID进行关联*/ WITH TMP_TBL AS (SELECT P.ROWID AS RID, MIN(CASE WHEN S.SALE_DATE >= P.PRO_DATE THEN S.SALE_DATE END) AS MIN_SALDATE FROM PRODUCT P LEFT JOIN SALDATE S ON P.ITEM_NO = S.ITEM_NO GROUP BY P.ROWID) SELECT P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, T.MIN_SALDATE FROM PRODUCT P LEFT JOIN TMP_TBL T ON P.ROWID = T.RID ORDER BY P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, T.MIN_SALDATE; /*下面这种不是等价改写,例如Product表中有重复数据时,检索结果可能不一样*/ SELECT P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, MIN(S.SALE_DATE) AS MIN_SALDATE FROM PRODUCT P LEFT JOIN SALDATE S ON P.ITEM_NO = S.ITEM_NO AND S.SALE_DATE >= P.PRO_DATE GROUP BY P.ITEM_NO, P.ITEM_NM, P.PRO_DATE ORDER BY P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, MIN_SALDATE;
主表带检索条件的不等连接的子查询改为连接查询
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table PRODUCT ( ITEM_NO VARCHAR2(10), ITEM_NM VARCHAR2(10), PRO_ADDRESS VARCHAR2(10), PRO_DATE VARCHAR2(10) ); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('001', 'A001', 'TOKYO', '04'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('002', 'A002', 'TOKYO', '04'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('003', 'A003', 'TOKYO', '07'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('004', 'A004', 'BEIJING', '08'); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE) values ('005', 'A005', 'BEIJING', '07'); commit; create table SALDATE ( ITEM_NO VARCHAR2(10), SALE_DATE VARCHAR2(10), BUY_DATE VARCHAR2(10) ) insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('001', '01', '01'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('001', '05', '09'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('001', '06', '07'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('002', '02', '12'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('002', '10', '10'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('003', '01', '13'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('003', '02', '02'); commit;
SELECT P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, (SELECT MIN(S.SALE_DATE) FROM SALDATE S WHERE S.ITEM_NO = P.ITEM_NO AND S.SALE_DATE >= P.PRO_DATE) AS MIN_SALDATE, (SELECT MIN(S.BUY_DATE) FROM SALDATE S WHERE S.ITEM_NO = P.ITEM_NO AND S.BUY_DATE >= P.PRO_DATE) AS MIN_SALDATE FROM PRODUCT P WHERE P.ITEM_NO='001'; WITH TMP_TBL AS (SELECT P.ROWID AS RID, MIN(CASE WHEN S.SALE_DATE >= P.PRO_DATE THEN S.SALE_DATE END) AS MIN_SALDATE, MIN(CASE WHEN S.BUY_DATE >= P.PRO_DATE THEN S.BUY_DATE END) AS MIN_BUYDATE FROM PRODUCT P LEFT JOIN SALDATE S ON P.ITEM_NO = S.ITEM_NO GROUP BY P.ROWID) SELECT P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, T.MIN_SALDATE, T.MIN_BUYDATE FROM PRODUCT P LEFT JOIN TMP_TBL T ON P.ROWID = T.RID WHERE P.ITEM_NO='001'; /*非等价改写*/ SELECT P.ITEM_NO, P.ITEM_NM, P.PRO_DATE, MIN(CASE WHEN S.SALE_DATE >= P.PRO_DATE THEN S.SALE_DATE END) AS MIN_SALDATE, MIN(CASE WHEN S.BUY_DATE >= P.PRO_DATE THEN S.BUY_DATE END) AS MIN_BUYDATE FROM PRODUCT P LEFT JOIN SALDATE S ON P.ITEM_NO = S.ITEM_NO WHERE P.ITEM_NO = '001' GROUP BY P.ITEM_NO, P.ITEM_NM, P.PRO_DATE;
2,子查询改为连接查询时RowId标示唯一行,比如有重复数据时。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table EMP ( EMPNO VARCHAR2(10), ENAME VARCHAR2(10), SAL VARCHAR2(10), DEPTNO VARCHAR2(10), SAL_DATE VARCHAR2(10) ); commit; insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A01', 'NA01', '1000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A02', 'NA02', '1000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A03', 'NA03', '2000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A04', 'NA04', '2000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A05', 'NA05', '3000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A06', 'NA06', '4000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A07', 'NA07', '5000', null, null); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A06', 'NA06', '6000', null, null); commit; create table EMP1 ( EMPNO VARCHAR2(10), ENAME VARCHAR2(10), SAL VARCHAR2(10), DEPTNO VARCHAR2(10), SAL_DATE VARCHAR2(10) ); commit; insert into EMP1 (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A01', 'NA01', '950', null, null); insert into EMP1 (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A02', 'NA02', '1050', null, null); insert into EMP1 (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A03', 'NA03', '1950', null, null); insert into EMP1 (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A04', 'NA04', '2050', null, null); insert into EMP1 (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A06', 'NA06', '3950', null, null); insert into EMP1 (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A07', 'NA07', '5000', null, null); commit;
SELECT E.EMPNO, E.SAL, (SELECT SUM(E1.SAL) FROM EMP1 E1 WHERE E1.SAL >= E.SAL-100 AND E1.SAL <= E.SAL) AS SUM_SAL_B4, T.SUM_SAL_AF FROM EMP E LEFT JOIN (SELECT EE.SAL, SUM(E2.SAL) AS SUM_SAL_AF FROM EMP1 E2 INNER JOIN EMP EE ON E2.SAL BETWEEN EE.SAL - 100 AND EE.SAL GROUP BY EE.SAL) T ON E.SAL = T.SAL ORDER BY E.EMPNO; SELECT E.EMPNO, E.SAL, (SELECT SUM(E1.SAL) FROM EMP1 E1 WHERE E1.SAL >= E.SAL-100 AND E1.SAL <= E.SAL) AS SUM_SAL_B4, T.SUM_SAL_AF FROM EMP E LEFT JOIN (SELECT EE.ROWID AS RID, SUM(E2.SAL) AS SUM_SAL_AF FROM EMP1 E2 INNER JOIN EMP EE ON E2.SAL BETWEEN EE.SAL - 100 AND EE.SAL GROUP BY EE.ROWID) T ON E.ROWID = T.RID ORDER BY E.EMPNO
3,不等连接查询
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table PRODUCT ( ITEM_NO VARCHAR2(10), ITEM_NM VARCHAR2(10), PRO_ADDRESS VARCHAR2(10), PRO_DATE VARCHAR2(10), PRICE NUMBER ); commit; insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('001', 'A001', 'TOKYO', '04', 100); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('002', 'A002', 'TOKYO', '04', 200); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('003', 'A003', 'TOKYO', '07', 300); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('004', 'A004', 'BEIJING', '08', 400); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('005', 'A005', 'BEIJING', '07', 200); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('001', 'A001', 'TOKYO', '03', 300); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('001', 'A001', 'BEIJING', '03', 200); insert into PRODUCT (ITEM_NO, ITEM_NM, PRO_ADDRESS, PRO_DATE, PRICE) values ('002', 'A002', 'SHANGHAI', '03', 500); commit; create table SALDATE ( ITEM_NO VARCHAR2(10), SALE_DATE VARCHAR2(10), BUY_DATE VARCHAR2(10) ); commit; insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('001', '01', '10'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('001', '05', '09'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('001', '06', '07'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('002', '02', '12'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('002', '10', '10'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('003', '01', '13'); insert into SALDATE (ITEM_NO, SALE_DATE, BUY_DATE) values ('003', '02', '20'); commit;
SELECT P.ITEM_NO, SUM(P.PRICE) AS SUM_PRICE FROM PRODUCT P INNER JOIN SALDATE S ON P.ITEM_NO = S.ITEM_NO AND P.PRO_DATE BETWEEN S.SALE_DATE AND S.BUY_DATE GROUP BY P.ITEM_NO
4,子查询改为连接查询时逻辑一致性
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
create table DEPT ( DEPTNO VARCHAR2(10), DNAME VARCHAR2(10) ); commit; insert into DEPT (DEPTNO, DNAME) values ('D01', 'ND01'); insert into DEPT (DEPTNO, DNAME) values ('D02', 'ND02'); insert into DEPT (DEPTNO, DNAME) values ('D03', 'ND03'); insert into DEPT (DEPTNO, DNAME) values ('D04', 'ND04'); insert into DEPT (DEPTNO, DNAME) values ('D01', 'ND01'); insert into DEPT (DEPTNO, DNAME) values ('D02', 'ND02'); insert into DEPT (DEPTNO, DNAME) values ('D03', 'ND03'); commit; create table EMP ( EMPNO VARCHAR2(10), ENAME VARCHAR2(10), SAL NUMBER, DEPTNO VARCHAR2(10), SAL_DATE VARCHAR2(10) ); commit; insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A01', 'NA01', 1000, 'D01', '03'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A02', 'NA02', 1000, 'D02', '04'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A03', 'NA03', 2000, 'D03', '05'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A04', 'NA04', 2000, 'D04', '06'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A05', 'NA05', 3000, 'D03', '07'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A06', 'NA06', 4000, 'D02', '08'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A07', 'NA07', 5000, 'D01', '09'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A06', 'NA06', 6000, 'D01', '10'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A01', 'NA01', 2000, 'D01', '01'); insert into EMP (EMPNO, ENAME, SAL, DEPTNO, SAL_DATE) values ('A02', 'NA02', 5000, 'D02', '02'); commit;
SELECT E.EMPNO, E.DEPTNO, (SELECT DISTINCT DNAME FROM DEPT D WHERE E.DEPTNO = D.DEPTNO) FROM EMP E /*原查询中E.EMPNO, E.DEPTNO没有去重复处理,此处不是等价改写*/ SELECT DISTINCT E.EMPNO, E.DEPTNO, D.DNAME FROM EMP E LEFT JOIN DEPT D ON E.DEPTNO = D.DEPTNO /*逻辑一致*/ SELECT E.EMPNO, E.DEPTNO, D.DNAME FROM EMP E LEFT JOIN (SELECT DISTINCT DNAME, DEPTNO FROM DEPT) D ON E.EMPNO =D.DEPTNO