MySQL中的復合查詢使用解讀
在實際開發(fā)中,僅用單表查詢顯然無法滿足復雜業(yè)務需求。今天我們就以經(jīng)典的員工管理系統(tǒng)(EMP員工表、DEPT部門表、SALGRADE工資級別表)為例,聊聊 MySQL 復合查詢的核心玩法 —— 從單表查詢到多表聯(lián)查、子查詢,再到合并查詢,每一步都附上真實查詢結(jié)果,幫你直觀理解。
一、先回顧:單表查詢的基礎(chǔ)操作(以EMP表為例)
先明確EMP表基礎(chǔ)數(shù)據(jù)(對應圖片中表內(nèi)容):
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
|---|---|---|---|---|---|---|---|
| 7369 | SMITH | CLERK | 7902 | 1980-12-17 | 800 | NULL | 20 |
| 7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 | 1600 | 300 | 30 |
| 7521 | WARD | SALESMAN | 7698 | 1981-02-22 | 1250 | 500 | 30 |
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975 | NULL | 20 |
| 7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 | 1250 | 1400 | 30 |
| 7698 | BLAKE | MANAGER | 7839 | 1981-05-01 | 2850 | NULL | 30 |
| 7782 | CLARK | MANAGER | 7839 | 1981-06-09 | 2450 | NULL | 10 |
| 7788 | SCOTT | ANALYST | 7566 | 1987-04-19 | 3000 | NULL | 20 |
| 7839 | KING | PRESIDENT | NULL | 1981-11-17 | 5000 | NULL | 10 |
| 7844 | TURNER | SALESMAN | 7698 | 1981-09-08 | 1500 | 0 | 30 |
| 7876 | ADAMS | CLERK | 7788 | 1987-05-23 | 1100 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950 | NULL | 30 |
| 7902 | FORD | ANALYST | 7566 | 1981-12-03 | 3000 | NULL | 20 |
| 7934 | MILLER | CLERK | 7782 | 1982-01-23 | 1300 | NULL | 10 |
1. 帶條件的篩選
SELECT * FROM EMP WHERE (sal>500 OR job='MANAGER') AND ename LIKE 'J%';
查詢結(jié)果:
| empno | ename | job | mgr | hiredate | sal | comm | deptno |
|---|---|---|---|---|---|---|---|
| 7566 | JONES | MANAGER | 7839 | 1981-04-02 | 2975 | NULL | 20 |
| 7900 | JAMES | CLERK | 7698 | 1981-12-03 | 950 | NULL | 30 |
2. 排序與計算字段
(1)按部門號升序、工資降序排列
SELECT * FROM EMP ORDER BY deptno, sal DESC;
查詢結(jié)果(節(jié)選核心字段):
| empno | ename | sal | deptno |
|---|---|---|---|
| 7839 | KING | 5000 | 10 |
| 7782 | CLARK | 2450 | 10 |
| 7934 | MILLER | 1300 | 10 |
| 7788 | SCOTT | 3000 | 20 |
| 7902 | FORD | 3000 | 20 |
| 7566 | JONES | 2975 | 20 |
| 7876 | ADAMS | 1100 | 20 |
| 7369 | SMITH | 800 | 20 |
| 7698 | BLAKE | 2850 | 30 |
| 7499 | ALLEN | 1600 | 30 |
| 7844 | TURNER | 1500 | 30 |
| 7521 | WARD | 1250 | 30 |
| 7654 | MARTIN | 1250 | 30 |
| 7900 | JAMES | 950 | 30 |
(2)計算年薪(工資 ×12 + 獎金,獎金為空則按 0 算)并排序
SELECT ename, sal*12+IFNULL(comm,0) AS '年薪' FROM EMP ORDER BY 年薪 DESC;
查詢結(jié)果:
| ename | 年薪 |
|---|---|
| KING | 60000 |
| SCOTT | 36000 |
| FORD | 36000 |
| JONES | 35700 |
| BLAKE | 34200 |
| CLARK | 29400 |
| ALLEN | 19500 |
| TURNER | 18000 |
| MARTIN | 16400 |
| MILLER | 15600 |
| WARD | 15500 |
| ADAMS | 13200 |
| JAMES | 11400 |
| SMITH | 9600 |
3. 聚合與分組查詢
(1)查每個部門的平均工資、最高工資
SELECT deptno, FORMAT(AVG(sal),2) AS avg_sal, MAX(sal) AS max_sal FROM EMP GROUP BY deptno;
查詢結(jié)果:
| deptno | avg_sal | max_sal |
|---|---|---|
| 10 | 2,916.67 | 5000 |
| 20 | 2,175.00 | 3000 |
| 30 | 1,566.67 | 2850 |
(2)篩選平均工資 < 2000的部門
SELECT deptno, AVG(sal) AS avg_sal FROM EMP GROUP BY deptno HAVING avg_sal<2000;
查詢結(jié)果:
| deptno | avg_sal |
|---|---|
| 30 | 1566.6667 |
二、多表查詢:跨表關(guān)聯(lián)數(shù)據(jù)
先明確關(guān)聯(lián)表基礎(chǔ)數(shù)據(jù):
DEPT部門表
| deptno | dname | loc |
|---|---|---|
| 10 | ACCOUNTING | NEW YORK |
| 20 | RESEARCH | DALLAS |
| 30 | SALES | CHICAGO |
| 40 | OPERATIONS | BOSTON |
SALGRADE工資級別表
| grade | losal | hisal |
|---|---|---|
| 1 | 700 | 1200 |
| 2 | 1201 | 1400 |
| 3 | 1401 | 2000 |
| 4 | 2001 | 3000 |
| 5 | 3001 | 9999 |
1. 基礎(chǔ)多表聯(lián)查(等值連接)
(1)查 “員工名、工資、所屬部門名”
SELECT EMP.ename, EMP.sal, DEPT.dname FROM EMP, DEPT WHERE EMP.deptno = DEPT.deptno;
查詢結(jié)果(節(jié)選):
| ename | sal | dname |
|---|---|---|
| SMITH | 800 | RESEARCH |
| ALLEN | 1600 | SALES |
| WARD | 1250 | SALES |
| JONES | 2975 | RESEARCH |
| MARTIN | 1250 | SALES |
| BLAKE | 2850 | SALES |
| CLARK | 2450 | ACCOUNTING |
| SCOTT | 3000 | RESEARCH |
| KING | 5000 | ACCOUNTING |
| TURNER | 1500 | SALES |
| ADAMS | 1100 | RESEARCH |
| JAMES | 950 | SALES |
| FORD | 3000 | RESEARCH |
| MILLER | 1300 | ACCOUNTING |
(2)限定部門號為 10的員工
SELECT ename, sal, dname FROM EMP, DEPT WHERE EMP.deptno=DEPT.deptno AND DEPT.deptno=10;
查詢結(jié)果:
| ename | sal | dname |
|---|---|---|
| CLARK | 2450 | ACCOUNTING |
| KING | 5000 | ACCOUNTING |
| MILLER | 1300 | ACCOUNTING |
2. 三表聯(lián)查(含工資級別表)
SELECT ename, sal, grade FROM EMP, SALGRADE WHERE EMP.sal BETWEEN losal AND hisal;
查詢結(jié)果:
| ename | sal | grade |
|---|---|---|
| SMITH | 800 | 1 |
| ALLEN | 1600 | 3 |
| WARD | 1250 | 2 |
| JONES | 2975 | 4 |
| MARTIN | 1250 | 2 |
| BLAKE | 2850 | 4 |
| CLARK | 2450 | 4 |
| SCOTT | 3000 | 4 |
| KING | 5000 | 5 |
| TURNER | 1500 | 3 |
| ADAMS | 1100 | 1 |
| JAMES | 950 | 1 |
| FORD | 3000 | 4 |
| MILLER | 1300 | 2 |
三、自連接:同一張表查上下級
-- 別名leader代表領(lǐng)導,worker代表員工 SELECT leader.empno, leader.ename FROM emp leader, emp worker WHERE leader.empno = worker.mgr AND worker.ename='FORD';
查詢結(jié)果:
| empno | ename |
|---|---|
| 7566 | JONES |
四、子查詢:用查詢結(jié)果當條件 / 臨時表
1. 單行子查詢(返回一條結(jié)果)
SELECT ename, job FROM EMP WHERE sal = (SELECT MAX(sal) FROM EMP);
查詢結(jié)果:
| ename | job |
|---|---|
| KING | PRESIDENT |
2. 多行子查詢(返回多條結(jié)果)
(1)查 “和 10 號部門崗位相同、但不屬于 10 號部門” 的員工
SELECT ename,job,sal,deptno FROM emp WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno=10) AND deptno<>10;
查詢結(jié)果:
| ename | job | sal | deptno |
|---|---|---|---|
| JONES | MANAGER | 2975 | 20 |
| BLAKE | MANAGER | 2850 | 30 |
| SMITH | CLERK | 800 | 20 |
| ADAMS | CLERK | 1100 | 20 |
| JAMES | CLERK | 950 | 30 |
(2)查 “工資比 30 號部門所有員工都高” 的員工
SELECT ename, sal, deptno FROM EMP WHERE sal > ALL(SELECT sal FROM EMP WHERE deptno=30);
查詢結(jié)果:
| ename | sal | deptno |
|---|---|---|
| JONES | 2975 | 20 |
| SCOTT | 3000 | 20 |
| KING | 5000 | 10 |
| FORD | 3000 | 20 |
3. from 子句子查詢(把子查詢當臨時表)
-- 先查各部門平均工資(臨時表tmp),再關(guān)聯(lián)員工表 SELECT ename, deptno, sal, FORMAT(tmp.avg_sal,2) AS dept_avg_sal FROM EMP, (SELECT AVG(sal) avg_sal, deptno dt FROM EMP GROUP BY deptno) tmp WHERE EMP.sal > tmp.avg_sal AND EMP.deptno=tmp.dt;
查詢結(jié)果:
| ename | deptno | sal | dept_avg_sal |
|---|---|---|---|
| KING | 10 | 5000 | 2,916.67 |
| JONES | 20 | 2975 | 2,175.00 |
| SCOTT | 20 | 3000 | 2,175.00 |
| FORD | 20 | 3000 | 2,175.00 |
| BLAKE | 30 | 2850 | 1,566.67 |
| ALLEN | 30 | 1600 | 1,566.67 |
五、合并查詢:union/union all
1. union(自動去重)
SELECT ename, sal, job FROM EMP WHERE sal>2500 UNION SELECT ename, sal, job FROM EMP WHERE job='MANAGER';
查詢結(jié)果(無重復數(shù)據(jù)):
| ename | sal | job |
|---|---|---|
| JONES | 2975 | MANAGER |
| BLAKE | 2850 | MANAGER |
| SCOTT | 3000 | ANALYST |
| KING | 5000 | PRESIDENT |
| FORD | 3000 | ANALYST |
| CLARK | 2450 | MANAGER |
2. union all(保留重復)
SELECT ename, sal, job FROM EMP WHERE sal>2500 UNION ALL SELECT ename, sal, job FROM EMP WHERE job='MANAGER';
查詢結(jié)果(JONES、BLAKE 重復出現(xiàn)):
| ename | sal | job |
|---|---|---|
| JONES | 2975 | MANAGER |
| BLAKE | 2850 | MANAGER |
| SCOTT | 3000 | ANALYST |
| KING | 5000 | PRESIDENT |
| FORD | 3000 | ANALYST |
| JONES | 2975 | MANAGER |
| BLAKE | 2850 | MANAGER |
| CLARK | 2450 | MANAGER |
總結(jié)
MySQL 復合查詢是實際開發(fā)的核心技能,核心是理清表關(guān)系、靈活組合單表 / 多表 / 子查詢語法。
本文所有示例均基于真實員工管理表數(shù)據(jù),查詢結(jié)果可直接驗證,建議你復制 SQL 語句在本地數(shù)據(jù)庫中實操,更快掌握各類查詢技巧~
這些僅為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL中的CONCAT()函數(shù):輕松拼接字符串的利器
這篇文章主要介紹了MySQL中的CONCAT()函數(shù):輕松拼接字符串的利器,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04
解決windows下mysql8修改my.ini設置datadir后無法啟動問題
在修改MySQL的my.ini文件以更改數(shù)據(jù)目錄后,可能會遇到無法啟動的問題,這通常是因為字符編碼被改變或新路徑權(quán)限不足,正確的做法是備份my.ini文件,確保使用ANSI字符編碼修改datadir,并確保新路徑有足夠的權(quán)限,特別是SYSTEM或NETWORKSERVICE權(quán)限2025-01-01

