1. 程式人生 > >對於MySQL中的子查詢的理解

對於MySQL中的子查詢的理解

每天記錄一下自己的心得體會,今天寫一下MySQL中的子查詢,個人感覺子查詢的難度比之前學的查詢都比較難,可能是語句太多吧,對於初學者的難度會有一點,反正我第一次接觸的時候是崩潰的,因為·程式碼有點多,因為內容比較多,所以小弟要是有講的不到位的,希望各位在下面給出建議,好了,話不多說,我們先來建三張表

CREATE TABLE EMP(
      EMPNO  INT,
       ENAME  VARCHAR(50),
       JOB  VARCHAR(20),
       MGR INT,
        HIREDATE  DATE,
         SAL  DECIMAL
(7,2), COMM DECIMAL(7,2), DEPTNO INT );
INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1001,'錘石','文員',1013,'2000-12-17',8000.00,NULL,20); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1002,'女警','銷售員',1006,'2001-2-20',16000.00,3000.00,30); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES
(1003,'小黃毛','銷售員',1006,'2001-2-22',12500.00,5000.00,30);
INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1004,'劍聖','經理',1009,'2001-04-02',29750.00,NULL,20); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1005,'老鼠','銷售員',1006,'2001-9-28',12500.00,14000.00,30); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES
(1006,'蠻子','經理',1009,'2000-05-01',28500.00,NULL,30);
INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1007,'菊花信','經理',1009,'2001-09-01',24500.00,NULL,10); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1008,'獅子狗','分析師',1004,'2007-04-19',30000.00,NULL,20); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1009,'猴哥','董事長',NULL,'2001-11-17',50000.00,NULL,10); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1010,'奧巴馬','銷售員',1006,'2001-09-08',15000.00,0.00,30); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1011,'牛頭','文員',1008,'2007-05-23',11000.00,NULL,20); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1012,'風女','文員',1006,'2001-12-03',9500.00,NULL,30); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1013,'螳螂','分析師',1004,'2001-12-03',30000.00,NULL,20); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1014,'奶媽','銷售員',1007,'2002-01-23',13000.00,NULL,10); INSERT INTO EMP (EMPNO,ENAME,JOB,MGR,HIREDATE,SAL,COMM,DEPTNO) VALUES (1015,'花千骨','文員',1001,'2000-12-17',80000.00,NULL,50); SELECT * FROM EMP;

這一張是員工資訊表

CREATE TABLE dept(
    deptno      INT     PRIMARY KEY,
    dname       VARCHAR(50),
    loc         VARCHAR(50)
);

CREATE TABLE salgrade(
    grade       INT     PRIMARY KEY,
    losal       INT,
    hisal       INT
);

INSERT INTO dept VALUES (10, '教研部', '北京');
INSERT INTO dept VALUES (20, '學工部', '上海');
INSERT INTO dept VALUES (30, '銷售部', '廣州');
INSERT INTO dept VALUES (40, '財務部', '武漢');



INSERT INTO salgrade VALUES (1, 7000, 12000);
INSERT INTO salgrade VALUES (2, 12010, 14000);
INSERT INTO salgrade VALUES (3, 14010, 20000);
INSERT INTO salgrade VALUES (4, 20010, 30000);
INSERT INTO salgrade VALUES (5, 30010, 99990);

SHOW TABLES;
SELECT * FROM emp;
SELECT * FROM dept;
SELECT * FROM salgrade;

接下來的這兩張是部門資訊表和工資等級表 在我看來子查詢就是將某個查詢結果做為另一條查詢語句的條件或者另一張表,也就是說將a查詢語句放在b查詢語句的表名位置或者是條件的位置 下面我會通過幾個經典的查詢語句來進行說明(可能會涉及多表查詢) 1. 列出受僱日期早於直接上級的所有員工的編號、姓名、部門名稱。 首先對於這種查詢我們需要有自己的思路 第一,篩選出員工的直接上級 第二,篩選受僱日期早於直接上級的所有員工的編號,姓名 租後,左外連線部門表完成查詢 以下為程式碼:

select emp.empno,emp.ename,dept.dname 
from emp left join (select ename,empno,hiredate
            from emp) e1
on emp.mgr=e1.empno
left join dept 
on emp.deptno=dept.deptno 
where emp.hiredate<e1.hiredate;
  1. 列出部門名稱和這些部門的員工資訊,同時列出那些沒有員工的部門。 第一點需要知道部門表需要全部顯示 第二個,需要知道員工需要與部門表對應 程式碼如下
select dept.dname,emp.*
from dept left join emp 
on dept.deptno=emp.deptno;
  1. 列出最低薪金大於15000的各種工作及從事此工作的員工人數。
select job,count(*)
from emp
group by job 
having min(sal)>15000;
  1. 列出在銷售部工作的員工的姓名,假定不知道銷售部的部門編號。
select ename 
from emp 
where empno!=10 and empno!=20 and empno!=40;
  1. 列出薪金高於公司平均薪金的所有員工資訊,所在部門名稱,上級領導,工資等級。
SELECT AVG(sal) FROM emp;
SELECT emp.*,dept.`dname`,e2.ename,salgrade.`grade`
FROM emp LEFT JOIN dept 
ON emp.`DEPTNO`=dept.`deptno`
LEFT JOIN (SELECT ename,empno
            FROM emp) e2
ON emp.`MGR`=e2.empno 
LEFT JOIN salgrade
ON sal BETWEEN losal AND hisal
HAVING sal>(SELECT AVG(sal) FROM emp);

6.列出與獅子狗從事相同工作的所有員工及部門名稱。

SELECT emp.`ENAME`,dept.`dname` 
FROM emp LEFT JOIN dept
ON emp.`DEPTNO`=dept.`deptno`
WHERE job = (SELECT job 
            FROM emp
            WHERE ename = "獅子狗");

7.列出薪金高於在部門30工作的所有員工的薪金 的員工姓名和薪金、部門名稱

SELECT emp.`ENAME`,emp.`SAL`,dept.`dname`
FROM emp LEFT JOIN dept
ON emp.`DEPTNO`=dept.`deptno`
HAVING emp.`SAL`>(SELECT MAX(sal) FROM emp WHERE deptno=30);

下面補充一下,關於子查詢和多表查詢的一些定義 連線的分類 內連線: 只會找到滿足條件的資料,不滿足的會丟掉

select from b表1 inner join 表二 on 條件

外連線 左外連線 左邊的表中的資料一個都不能少 select from 表1 left outer join 表2 on 去除笛卡爾積條件 右外連線 右邊的表中的資料一個都不能少 select from 表1 right outer join 表2 on 去除笛卡爾積條件 全外連線(MySql不支援全外連線) 兩邊表中的資料一個都不能少。 MySql可以使用合併結果集的方式來模擬出全外連線。

合併結果集 通過合併結果集的方式模擬出其他資料庫的·全外連線的效果 合併結果集有兩種方式 1.全部合併在一起 不會去重 UNION ALL 2.全部合併在一起 會取出重複的結果 UNION

子查詢 我們可以將一個查詢當做條件 還可以將查詢結果當作一張表

內連線 SELECT * FROM emp INNER JOIN dept ON emp.deptno=dept.deptno; 外連線 左外連線 左表的資料一條都不能少 SELECT * FROM emp LEFT JOIN dept ON emp.deptno=dept.deptno; 查詢出所有員工的姓名和部門名稱 SELECT e.ename,IFNULL(d.dname,’無部門’) FROM emp e LEFT JOIN dept d ON e.deptno=d.deptno;

ifnull的用處,語法 IFNULL(可能存在null值的列,出現null值時取代它的值)