有一段時間沒作數據庫的題了,前面面試偶然作到這麼一題目,以爲不錯,憑記憶將題目記下來,而後在數據庫中實現了一遍。面試
題目大概是這樣: 一張員工表 employee,包含字段 id,name,salary,dep_no; 一張部門信息表 department,包含字段 id,dep_no,name,其中 employee 的 dep_no 關聯 department 的 dep_no;寫 sql 查出各部門超出部門平均薪資的員工的姓名,薪資,所在部門名稱及部門平均薪水。sql
下面是我建立的兩張表:數據庫
DROP TABLE IF EXISTS department; CREATE TABLE department ( id int NOT NULL auto_increment PRIMARY KEY, dep_no int NOT NULL, `name` VARCHAR(50) NOT NULL ); INSERT INTO department(dep_no,name) VALUES(10,'研發部'); INSERT INTO department(dep_no,name) VALUES(20,'測試部'); INSERT INTO department(dep_no,name) VALUES(30,'財務部');
DROP TABLE IF EXISTS employee; CREATE TABLE employee ( `id` int NOT NULL auto_increment, `name` varchar(50) NOT NULL , `salary` double(10,2) NOT NULL DEFAULT 0, `dep_no` INTEGER NOT NULL, PRIMARY KEY (`id`) ); INSERT INTO employee(name,salary,dep_no) SELECT 'Bruce',15000.00,dep_no FROM department WHERE `name` = '研發部'; INSERT INTO employee(name,salary,dep_no) SELECT 'Kevin',16000.00,dep_no FROM department WHERE `name` = '研發部'; INSERT INTO employee(name,salary,dep_no) SELECT 'Lww',12000.00,dep_no FROM department WHERE `name` = '財務部'; INSERT INTO employee(name,salary,dep_no) SELECT 'Linda',10000.00,dep_no FROM department WHERE `name` = '財務部'; INSERT INTO employee(name,salary,dep_no) SELECT 'David',10000.00,dep_no FROM department WHERE name = '測試部'; INSERT INTO employee(name,salary,dep_no) SELECT 'Sandy',8000.00,dep_no FROM department WHERE name = '測試部'; INSERT INTO employee(name,dep_no) SELECT 'Dennis' ,dep_no FROM department WHERE name = '測試部';
題目的分析:首先要獲得目標員工的姓名,薪資不用說要從 employee 表中得到;至於後兩個數據部門名稱及部門平均薪資,直接查 department 確定得不到,須要兩表聯立查詢,不妨就寫出這塊的 sql :測試
SELECT AVG(e.salary) AS avg_sal,d.dep_no,d.`name` FROM employee e,department d WHERE d.dep_no = e.dep_no GROUP BY d.dep_no,d.`name`;
這裏之因此 dep_no,name兩個字段做爲分組字段,是由於後面的查詢目標中有 name,而 dep_no 做爲部門的一個惟一標識,它是自然的分組字段,同時考慮到這一部中查詢結果要與 employee 表聯立,而二者之又只能以 dep_no 鏈接,而通常狀況下不會出現一個部門對應多個部門號的狀況,因此 group by dep_no 與 group by dep_no,name 正常狀況下結果應該是同樣的。spa
將上面的結果做爲臨時表 tmp 放入主查詢,最終獲得:code
SELECT e.`name`,e.salary,tmp.dep_name,tmp.avg_sal FROM employee e,( SELECT AVG(e.salary) AS avg_sal,d.dep_no,d.`name` AS dep_name FROM employee e,department d WHERE d.dep_no = e.dep_no GROUP BY d.dep_no,d.`name` )tmp WHERE e.dep_no = tmp.dep_no AND e.salary > tmp.avg_sal;
固然,若是真的存在一個 name 對應多個 dep_no 或者說存在不一樣部門取同一個名稱的狀況 ,那麼也可用下面的方式獲得正確結果:blog
SELECT e.`name`,e.salary,d.`name` AS dep_name,tmp.avg_sal FROM employee e,department d,( SELECT AVG(e.salary) AS avg_sal,d.dep_no FROM employee e,department d WHERE d.dep_no = e.dep_no GROUP BY d.dep_no )tmp WHERE e.dep_no = tmp.dep_no AND e.dep_no = d.dep_no AND e.salary > tmp.avg_sal;
仍是將 dep_no 做爲惟一分組字段,外層查詢再關聯 department 就好了。rem
PS: 搜了一圈,好像其餘地方也有相似這樣的題目,但我以爲我作的這一版仍是很細緻的,頗有參考價值。class