MySQL基礎知識總結1/3(查詢語句DQL)

目錄

一、基礎查詢介紹

1、起別名

2、去重

3、+號的作用

4、使用concat實現連接

5、IFNULL

二、條件查詢

一、按條件表達式篩選

二、按邏輯表達式篩選

 三、模糊查詢

1、like

2、between  and

3、in關鍵字

4、  is null

5、安全等於 <=>

測試題:

三、排序查詢

四、常見函數

一、字符函數

二、數學函數

三、日期函數

四、流程控制函數

五、case結構

案例練習

六、分組函數    

1、  簡單的使用:

2、分組函數的特點

3、和distinct搭配

4、count函數的詳細介紹

5、分組函數的其他注意事項 

案例複習

五、分組查詢的介紹 

分組查詢的簡單使用 

添加篩選條件 

分組前篩選

分組後篩選

按表達式或函數分組 

按多個字段分組

添加排序

小結

案例練習

六、連接查詢

笛卡爾乘積

連接查詢的分類

等值連接

等值連接的示例 

小結 

非等值連接 

自連接

測試題

SQL練習

sql99語法介紹

內連接

等值連接 

非等值連接

自連接 

左右連接

全外連接

交叉連接

查詢總結

​案例講解

子查詢 

where和having後面的子查詢

標量子查詢

列子查詢(多行子查詢)

行子查詢

exits後面的子查詢(相關子查詢)

案例

分頁查詢

測試題

子查詢經典案例

七、聯合查詢 

 


一、基礎查詢介紹

1、起別名

優點:

①便於理解

②如果要查詢的字段有重名的情況,使用別名可以區分開來

#方式一

‘As‘形式

SELECT first_name As "名字", salary As "薪水" FROM `employees`;

#方式二 

’空格’形式

SELECT first_name "名字", salary "薪水" FROM employees; #MySQL建議別名加雙引號

2、去重

#案例:查詢員工表中涉及到的所有的部門編號

SELECT department_id FROM `employees`

加入DISTINCT關鍵字

SELECT DISTINCT department_id FROM `employees`

3、+號的作用

Java中的+號

①運算符,兩個操作數都爲數值型,則做加法運算

②連接符,只要有一個操作數爲字符串

MySQL中的+號

僅有一個功能:運算符

~兩個操作數爲數值型,則做加法運算

select 100+20

~其中一方爲字符型,試圖將字符型數值轉成數值型

如果轉換成功,則繼續做加法運算,如果轉換失敗,則將字符型數值轉成0

SELECT '100'+20
SELECT 'jiusen'+20

 

 ~只要一方爲null,則結果肯定爲null

SELECT  NULL + 20

4、使用concat實現連接

SELECT CONCAT('a', 'b', 'c')

#案例:查詢員工名和姓連接成一個字段,並顯示爲姓名

SELECT 
  CONCAT(last_name, first_name) AS 姓名 
FROM
  employees 

5、IFNULL

SELECT 
  IFNULL(`commission_pct`, 0) AS 獎金率,
  commission_pct 
FROM
  employees 

二、條件查詢

語法:

SELECT 
  查詢列表 
FROM
  表名 
WHERE 篩選條件 

分類:

一、按條件表達式篩選

簡單條件運算符:  >   <   =   !=   <>   >=   <=

二、按邏輯表達式篩選

&&   ||    !    and  or   not 

三、模糊查詢

like 

between  and 

in

is  null 

一、按條件表達式篩選

#案例1 : 查詢工資 > 12000的員工信息 

SELECT 
  * 
FROM
  employees 
WHERE salary > 12000 

 #案例2: 查詢部門編號不等於30號的員工名和部門編號

select 
  `employee_id`,
  `department_id` 
from
  `employees` 
where `department_id` <> 30 

二、按邏輯表達式篩選

#案例1:查詢工資在10000到20000之間的員工名、工資以及獎金

SELECT 
  `last_name`,
  `salary`,
  `commission_pct` 
FROM
  `employees` 
WHERE salary >= 10000 
  AND salary <= 20000 

 

#案例2:查詢部門編號不是在90到110之間,或者工資高於15000的員工信息

SELECT 
  * 
FROM
  `employees` 
WHERE AND(
    `department_id` >= 90 
    AND `department_id` <= 110
  ) 
  OR `salary` > 15000 

 三、模糊查詢

1、like

特點①一般和通配符搭配使用

通配符: %任意多個字符,包含0個字符

              _任意單個字符

#案例1::查詢員工名中包含字符a的員工信息

SELECT 
  * 
FROM
  `employees` 
WHERE `last_name` LIKE '%a%' 

 #案例2:查詢員工名中第三個字符爲n,第五個字符爲a的員工名

SELECT 
  `last_name`,
  `salary` 
FROM
  `employees` 
WHERE `last_name` LIKE '__n_r%' 

 #案例3:查詢員工名中第三個字符爲_的員工名

-- 使用 '\'轉義字符進行轉義
SELECT 
  `last_name` 
FROM
  `employees` 
WHERE `last_name` LIKE '_\_%';

-- 使用ESCAPE關鍵字
SELECT 
  `last_name` 
FROM
  `employees` 
WHERE `last_name` LIKE '_$_%' ESCAPE '$'; 

2、between  and

①使用between and  可以提高語句的簡介度

②包含臨界值

③兩個臨界值不能更換位置

#案例1:查詢員工編號在100到120之間的員工信息

select 
  * 
from
  `employees` 
where `employee_id` between 100 and 120 

3、in關鍵字

#案例:查詢員工的工種編號是IT_PROG 、AD_VP、  AD_PRES中的一個員工名和工種編號

SELECT 
  `last_name`,
  `job_id` 
FROM
  `employees` 
WHERE `job_id` IN ('IT_PROG', 'AD_PRES', 'AD_VP') ;

4、  is null

=或者<>不能用於判斷null值

is null  或者 is not null可以判斷 null 值

#案例:查詢沒有獎金的員工名和獎金率

SELECT 
  `last_name`,
  `commission_pct` 
FROM
  `employees` 
WHERE `commission_pct` IS NULL ;

5、安全等於 <=>

IS NULL : 僅僅可以判斷NULL值,可讀性較高

<=> : 既可以判斷NULL值,又可以判斷普通的數值,可讀性較低

#案例1:查詢沒有獎金的員工名和獎金率

select 
  `last_name`,
  `commission_pct` 
from
  `employees` 
where `commission_pct` <=> null ;

#案例2:查詢薪資爲12000的員工名和薪資

SELECT 
  `last_name`,
  `salary` 
FROM
  `employees` 
WHERE salary <=> 12000 

#案例:查詢員工號爲176的員工號、姓名、月薪、獎金率、年薪

SELECT 
  `last_name`,
  `department_id`,
  `salary`,
  `commission_pct`,
  salary * 12 *(1+ IFNULL(commission_pct, 0)) AS 年薪 
FROM
  employees 
  WHERE `employee_id` = 176;

測試題:

#測試1: 查詢沒有獎金,且工資小於18000的salary, last_name

SELECT 
  `salary`,
  `last_name` 
FROM
  `employees` 
WHERE `commission_pct` IS NULL 
  AND `salary` < 18000 ;

#測試2:查詢employees表中,job_id不爲'IT'或者工資爲12000的員工信息

SELECT 
  * 
FROM
  `employees` 
WHERE `job_id` <> 'IT' 
  OR `salary` = 12000 ;

#測試3:查看部門departments表的結構

DESC `employees`;

 

#測試4:查詢部門departments表中涉及到了哪些位置編號

SELECT DISTINCT 
  `location_id` 
FROM
  `departments` 

## 經典面試題:

試問 SELECT * FROM `employees` ;  和 SELECT * FROM `employees` WHERE `commission_pct` LIKE '%%' AND `last_name` LIKE '%%';  結果是否一樣?並說明原因

SELECT * FROM `employees`;

SELECT * FROM `employees` WHERE `commission_pct` LIKE '%%' AND `last_name` LIKE '%%';

 第二種不能夠查詢到null的情況

三、排序查詢

語法:

select 查詢列表  from  表  【where  篩選條件】 order  by  排序列表  asc | desc

特點:

1、asc代表的是升序,desc代表的是降序

如果不寫,默認是升序

2、order by子句中可以支持單個字段、多個字段、表達式、函數、別名

3、order by子句一般是放在查詢語句的最後面,limit子句除外

 

# 案例1:查詢員工信息,要求工資從高到低排序

SELECT 
  * 
FROM
  `employees` 
ORDER BY `salary` DESC 

# 案例2:查詢部門編號 >= 90的員工信息,按入職時間的先後進行排序

SELECT 
  * 
FROM
  `employees` 
WHERE `department_id` >= 90 
ORDER BY hiredate ASC 

 # 案例3:按年薪的高低顯示員工的信息和 年薪【按表達式進行排序】

select 
  *,
  salary * 12 * (1+ ifnull(commission_pct, 0)) as '年薪' 
from
  `employees` 
order by 年薪;

#案例5:按姓名的長度顯示員工的姓名和工資【按函數進行排序】

SELECT 
  LENGTH(last_name) 字節長度,
  `last_name`,
  `salary` 
FROM
  `employees` 
ORDER BY LENGTH(last_name) ;

 

# 案例6:查詢員工信息,要求先按工資升序,再按員工編號降序【按多個字段排序】

SELECT 
  * 
FROM
  `employees` 
ORDER BY salary ASC,
  `employee_id` DESC ;

 ## 排序案例

#1、查詢員工的姓名和部門號和年薪,按年薪降序  按姓名升序

SELECT 
  `last_name`,
  `department_id`,
  `salary` * 12 * (1+ IFNULL(`commission_pct`, 0)) AS 年薪 
FROM
  `employees` 
ORDER BY 年薪 DESC,
  `last_name` ASC ;

#2、選擇工資不在8000到17000的員工的姓名和工資,按工資降序

SELECT 
  `last_name`,
  `salary` 
FROM
  `employees` 
WHERE salary NOT BETWEEN 8000 
  AND 17000 
ORDER BY salary DESC ;

#3、查詢郵箱中包含e的員工信息,並先按郵箱的字節數降序,再按部門號升序

SELECT 
  * 
FROM
  `employees` 
WHERE `email` LIKE '%e%' 
ORDER BY LENGTH(email) DESC,
  `department_id` ASC ;

四、常見函數

概念:類似於Java的方法,將一組邏輯語句封裝在方法中,對外暴露方法名

好處:1、隱藏了實現細節, 2、提高了代碼的重用性

調用:select 函數名(實參列表) 【from表】;

特點:①叫什麼(函數名) ②幹什麼(函數功能)

分類:

1、單行函數   如  concat 、length 、ifnull等

2、分組函數  功能:做統計使用,又稱爲統計函數 、 聚合函數、組函數

一、字符函數

#1、length 獲取參數值的字節個數

SELECT LENGTH('john');
SELECT LENGTH('森哥哥521');

#2、concat拼接字符串

SELECT CONCAT('郭', 'love', '張');

#3、upper、lower

SELECT UPPER('love'), LOWER('AK');  -- 字符串記得加上''或者""

#4、substr、substring

MySQL中索引從1開始

#截取從指定索引後面的所有字符

select substr('郭久森愛上了張瑩瑩', 7) output;

#截取從指定索引處指定字符長度的字符

select substr('郭久森愛上了張瑩瑩',1,3) output;

## 案例:姓名中首字符大寫,其他字符小寫然後用_拼接,顯示出來

SELECT 
  CONCAT(
    UPPER(SUBSTR(`last_name`, 1, 1)),
    '-',
    LOWER(SUBSTR(`last_name`, 2))
  ) 姓名 
FROM
  `employees` 

 #5、instr

返回指定字符串第一次出現的索引,如果找不到就返回0

SELECT 
  INSTR(
    '郭久森愛上了張瑩瑩',
    '張瑩瑩'
  ) AS out_put ;

#6、trim

去除字符串中的空格

select 
  trim('aa' from 'aaaaaaaa森') as out_put ;

#7、lpad用指定的字符實現左填充指定長度

SELECT LPAD('森啊啊啊', 5, '*') output

#8、右填充與左填充類似

 

#9、replace替換指定字符串

SELECT 
  REPLACE(
    '郭久森愛上了計算機',
    '計算機',
    '張瑩瑩'
  ) AS output ;

二、數學函數

#round 四捨五入

SELECT ROUND(-1.56)
SELECT 
  ROUND(- 1.567, 2) 四捨五入 ;

#ceil 向上取整,返回>=該參數的最小整數

SELECT 
  CEIL(- 1.567) 向上取整 ;

#floor向下取整,返回<=該參數的最大整數

SELECT 
  FLOOR(- 1.567) 向下取整 ;

#截斷 truncate

SELECT 
  TRUNCATE(1.6654, 2)

#mod取餘 : a*a/b*b

SELECT 
  MOD(10, 3)

三、日期函數

#now返回當前的系統日期 + 時間

#curdate返回當前系統日期,不包含時間

#curtime返回當前時間,不包含日期

#年、月、日

SELECT 
  YEAR(NOW()); -- 年
SELECT 
  MONTH(NOW()); -- 月
SELECT 
  DAY(NOW());  -- 日

#str_to_date 將字符通過指定的格式轉換成日期

SELECT 
  STR_TO_DATE('4-3 1992', '%m-%d %Y')

##案例:查詢入職日期爲1992-4-3的員工信息

SELECT 
  * 
FROM
  `employees` 
WHERE `hiredate` = STR_TO_DATE('4-3 1992', '%m-%d %Y') ;

#date_format 將日期轉換成字符

SELECT 
  DATE_FORMAT(NOW(), '%Y年%m月%d日')

 

#案例:查詢有獎金的員工名和入職日期(xx月/xx日  xx年)

SELECT 
  `last_name`,
  DATE_FORMAT(`hiredate`, '%m月/%d日 %Y年') 入職日期 
FROM
  `employees` 
WHERE `commission_pct` IS NOT NULL ;

四、流程控制函數

#1、if函數: if   else的效果

SELECT IF(10>5,'大','小');

#查詢有獎金的員工: 

SELECT 
  `last_name`,
  `commission_pct`,
  IF(
    `commission_pct` IS NULL,
    '沒獎金,呵呵',
    '有獎金,嘻嘻'
  ) AS 備註 
FROM
  `employees` ;

五、case結構

MySQL中

1、類似於switch  ...   case...   default.....

case  要判斷的字段或者表達式

when 常量1  then要顯示的值1或語句1

when 常量2  then要顯示的值1或語句2

when 常量3  then要顯示的值1或語句3

......

else 要顯示的值n或語句n

end

 

## 案例:查詢員工的工資,要求:

部門號=30,顯示的工資爲1.1倍

部門號=40,顯示的工資爲1.2倍

部門號=50,顯示的工資爲1.3倍

其他部門,顯示的工資爲原工資

SELECT 
  `salary` 薪資,
  `department_id`,
  CASE
    `department_id` 
    WHEN 30 
    THEN 1.1 * `salary` 
    WHEN 40 
    THEN 1.2 * `salary` 
    WHEN 50 
    THEN 1.3 * `salary` 
    ELSE `salary` 
  END AS 新工資 
FROM
  `employees` ;

 

2、

case 

when  條件1  then  要顯示的值1或語句1

when  條件2  then  要顯示的值2或語句2

......

else   要顯示的值n或語句n

end

區別:

1比較適合於處理等值判斷。2、比較適合區間的判斷

 

## 查詢員工的工資的情況

如果工資>20000,顯示A級別

如果工資>15000,顯示B級別

如果工資>10000,顯示C級別

否則顯示D級別

SELECT 
  `salary`,
  -- 注意逗號不要忘記
  CASE
    WHEN `salary` > 20000 
    THEN 'A' 
    WHEN `salary` > 15000 
    THEN 'B' 
    WHEN `salary` > 10000 
    THEN 'C' 
    ELSE 'D' 
  END AS 工資級別 
FROM
  `employees` ;

案例練習

#1、顯示系統時間(注:日期+時間)

SELECT 
  NOW() AS 系統時間 ;

#2、查詢員工號、姓名、工資、以及工資提高百分之20後的結果(new  salary)

SELECT 
  `employee_id`,
  `last_name`,
  `salary`,
  `salary` * (1+0.02) AS 'new salary' 
FROM
  `employees` ;

#3、將員工的姓名按首字母排序,並寫出姓名的長度(LENGTH)

SELECT 
  `last_name`,
  SUBSTR(`last_name`, 1, 1) AS 首字母,
  LENGTH(`last_name`) 
FROM
  `employees` 
ORDER BY `last_name` 

#4、做一個查詢,產生下面的結果

SELECT 
  CONCAT(
    `last_name`,
    ' earns ',
    salary,
    ' monthly but wants ',
    salary * 3
  ) AS 'Dream Salary' 
FROM
  `employees` 
WHERE salary = 24000 

#5、使用case-when,按照下面的條件:

job_id         Grade
AD_PRES            A
ST_MAN               B
IT_PROG            C
SA_REP             D
ST_CLERK             E

產生下面結果:

SELECT 
  `job_id` AS job,
  CASE
    `job_id` 
    WHEN 'AD_PRES' 
    THEN 'A' 
    WHEN 'ST_MAN' 
    THEN 'B' 
    WHEN 'IT_PROG' 
    THEN 'C' 
    WHEN 'SA_REP' 
    THEN 'D' 
    WHEN 'ST_CLERK' 
    THEN 'E' 
  END AS 等級 
FROM
  `employees` 
WHERE job_id = 'AD_PRES' 

六、分組函數    

功能:用作統計使用,又稱爲聚合函數或統計函數或組函數

   分類:

sum  求和、 avg  平均值、 max  最大值、 min  最小值、 count  計算個數

 

1、  簡單的使用

1、sum求和:

SELECT 
  SUM(`salary`) 總薪資
FROM
  `employees` 

2、avg  平均值

SELECT 
  AVG(`salary`) 平均薪資
FROM
  `employees` 

3、max最大值

select 
  max(`salary`) 最高薪資
from
  `employees` 

4、min最小值

SELECT 
  MIN(`salary`) 最低薪資
FROM
  `employees` 

5、count計算個數

SELECT 
  COUNT(`last_name`)  總人數
FROM
  `employees` 

 ** 另外也可以這些分組函數一起使用

SELECT 
  COUNT(`last_name`) 總人數,
  SUM(`salary`) 總薪資,
  AVG(`salary`) 平均薪資,
  MAX(`salary`) 最高薪資,
  MIN(`salary`) 最低薪資 
FROM
  `employees` 

 

2、分組函數的特點

1、sum、avg一般用於處理數值型

     max、min、count可以處理任何類型

2、是否忽略null值

sum、avg、max、min、count忽略了null值

 

3、和distinct搭配

 例:

select 
  sum(distinct `salary`) 去重求和,
  sum(`salary`) 求和
from
  `employees` 

4、count函數的詳細介紹

SELECT 
  COUNT(`commission_pct`) 非空的總行數 
FROM
  `employees` 
SELECT 
  COUNT(*) 表的總行數
FROM
  `employees` 
SELECT 
  COUNT(1) 總行數 -- 常量代表將表的列置爲一個常量,然後統計一列中該常量的個數
FROM
  `employees` 

效率:

NYISAM存儲引擎下,COUNT(*)的效率最高

INNODB存儲引擎下,COUNT(*)和COUNT(1)的效率差不多,比COUNT(字段)要高一些 ,字段的話要進行一下判斷是否爲null

一般使用count(*)用作統計行數

5、分組函數的其他注意事項 

 和分組函數一同查詢的字段要求是group by後的字段(group by知識點後面總結)

案例複習

#1、查詢員工表中的最大入職時間和最小入職時間的相差天數(DIFFRENCE)

SELECT 
  DATEDIFF(MAX(`hiredate`), MIN(`hiredate`))  DIFFERENT
FROM
  `employees` 

#2、查詢部門編號爲90的員工個數

SELECT 
  COUNT(*) 員工號爲90的個數
FROM
  `employees` 
WHERE `department_id` = 90 

五、分組查詢的介紹 

 

語法:

select  分組函數,列(要求出現在group by的後面)

from   表

【where   篩選條件】

group   by   子組的列表

【order   by   子句】

注意:查詢列表必須特殊,要求是分組函數和group   by後出現的字段

分組查詢的簡單使用 

#  案例:查詢每個部門平均薪資 

select 
  avg(`salary`) 平均薪資,
  `department_id` 部門 
from
  `employees` 
group by `department_id` 

 # 案例:查詢每個工種最高工資

SELECT 
  MAX(`salary`) 最高工資,
  `job_id` 工種 
FROM
  `employees` 
  GROUP BY `job_id`

 

 # 案例:查詢每個位置上的部門個數

SELECT 
  COUNT(*) 部門個數,
  `location_id` 部門 
FROM
  `departments` 
GROUP BY `location_id` 

添加篩選條件 

分組前篩選

案例1:查詢郵箱中包含a字符的,每個部門的平均工資

SELECT 
  AVG(`salary`) 平均薪資,
  `department_id` 部門,
  `email` 郵箱 
FROM
  `employees` 
WHERE `email` LIKE '%a%' 
GROUP BY `department_id` 

 案例2:查詢有獎金的每個領導手下員工的最高工資

SELECT 
  MAX(`salary`) 最高工資,
  `manager_id` 部門
FROM
  `employees` 
WHERE `commission_pct` IS NOT NULL 
GROUP BY `manager_id` 

分組後篩選

#案例1:查詢哪個部門的員工個數>2 

SELECT 
  COUNT(*) 員工個數,
  `department_id` 部門 
FROM
  `employees` 
GROUP BY `department_id` 
HAVING COUNT(*) > 2 

#案例2、查詢每個工種有獎金的員工的最高工資>12000的工種編號和最高工資

對於稍微複雜的查詢,可以分部來解決

①查詢每個工種有獎金的員工的最高工資

SELECT 
  MAX(salary) 最高工資,
  `job_id` 工種 
FROM
  `employees` 
WHERE `commission_pct` IS NOT NULL 
GROUP BY job_id 

②根據①結果繼續篩選,最高工資>12000

select 
  max(salary) 最高工資,
  `job_id` 工種 
from
  `employees` 
where `commission_pct` is not null 
group by job_id 
having max(salary) > 12000 

#案例3:查詢領導編號>102的每個領導手下的最低工資>5000的領導編號,以及其最低工資

思路:先分組,再加篩選條件

SELECT 
  MIN(salary) 最低工資,
  manager_id 領導編號 
FROM
  employees 
WHERE manager_id > 102 
GROUP BY manager_id 
HAVING MIN(salary) > 5000 

 

按表達式或函數分組 

#案例:按員工姓名的長度分組,查詢每一組的員工個數,篩選員工個數>5的有哪些

分步解決:

①查詢每個長度的員工個數

SELECT 
  COUNT(*),
  LENGTH(last_name) 
FROM
  employees 
GROUP BY LENGTH(last_name)

②添加篩選條件

select 
  count(*)員工個數,
  length(last_name)名字長度 
from
  employees 
group by length(last_name)
having count(*)>5

 

按多個字段分組

 #案例:查詢每個部門每個工種的員工的平均工資

SELECT 
  AVG(salary),
  `department_id`,
  `job_id` 
FROM
  `employees` 
GROUP BY `job_id`,
  `department_id` 

添加排序

#案例:查詢每個部門每個工種的平均工資,並且按平均工資的高低顯示

SELECT 
  AVG(salary),
  `department_id`,
  `job_id` 
FROM
  `employees` 
GROUP BY `job_id`,
  `department_id` 
 ORDER BY AVG(salary)DESC;

小結

1、分組查詢中的篩選條件分爲兩類:

 

類型 數據源 位置 關鍵字
分組前篩選 原始表 group  by子句的前面 where
分組後篩選 分組後的結果集 group  by子句的後面 having

①分組函數做條件肯定是放在having字句中

②能用分組前篩選的,就優先考慮使用分組前篩選 

 

2、group  by子句支持單個字段分組,多個字段分組(多個字段之間用逗號隔開沒有順序要求),表達式或函數(用的較少)

3、也可以添加排序(排序放在整個分組查詢的最後)

案例練習

#1、查詢各job_id的員工工資的最大值,最小值,平均值,總和,並按job_id升序

SELECT 
  MAX(salary) 最大值,
  MIN(salary) 最小值,
  AVG(salary) 平均值,
  SUM(salary) 總和 
FROM
  `employees` 
GROUP BY job_id 
ORDER BY job_id 

#2、查詢員工最高工資和最低工資之間的差距 DIFFERENT

SELECT 
  MAX(salary) - MIN(salary) DIFFERENT 
FROM
  `employees` 

#3、查詢各個管理者手下員工的最低工資,其中最低工資不能低於6000,沒有管理者的員工不計算在內

SELECT 
  MIN(salary), `manager_id` 
FROM
  employees 
WHERE `manager_id` IS NOT NULL 
GROUP BY `manager_id` 
HAVING MIN(salary) >= 6000 

#4、查詢所有部門的編號,員工數量和工資平均值,並按平均工資降序

SELECT 
  COUNT(*) 員工數量,
  AVG(salary) 平均薪資,
  `department_id` 部門編號 
FROM
  `employees` 
GROUP BY `department_id` 

5、選擇具有各個job_id的員工數量

SELECT 
  COUNT(*)員工數量,
  job_id 
FROM
  `employees` 
GROUP BY `job_id` 

六、連接查詢

含義:又稱爲多表查詢,當查詢的字段來自於多個表時,就會用到連接查詢

笛卡爾乘積

假設表1有m行數據,表2有n行數據,則下方SQL處理後,則產生m*n條數據 

SELECT 
  `name`,
  `boyName`
FROM
  `beauty`,
  `boys` 

連接查詢的分類

按照年代分類:

sql92標準:僅僅支持內連接

sql99標準【推薦】:支持內連接、外連接(左外、右外)、交叉連接

按功能分類:

            內連接: 等值連接、非等值連接、自連接

            外連接:左外連接、右外連接、全外連接

            交叉連接

等值連接

#案例:查詢女神名和對應的男神名

先查詢出所有的,然後再加上條件 

select 
  `name`,
  `boyName` 
from
  `beauty`,
  `boys` 
where beauty.id = boys.id 

#2、查詢員工名和對應的部門名

SELECT 
  `last_name`,
  `department_name` 
FROM
  `employees`,
  `departments` 
WHERE departments.department_id = employees.department_id 

 

##3、查詢員工號、工種號、工種名 

SELECT 
  `last_name`,
  a.`job_id`,
  `job_title` 
FROM
  `employees` AS a,  -- 由於表名字段太長,這裏起別名
  `jobs` AS b 
WHERE a.`job_id` = b.`job_id` 

 

爲表起別名

①、提高語句的簡介度

②、區分多個重名的子段

注:如果爲表起了別名,則查詢的字段就不能使用原來的表明去限定

等值連接的示例 

#案例1、表名是否可以交換

可以

#案例2、查詢有獎金的員工名、部門名

SELECT 
  `last_name`,
  `department_name` ,
  `commission_pct`
FROM
  `departments` d,
  `employees` e 
WHERE d.`department_id` = e.`department_id` 
  AND e.`commission_pct` IS NOT NULL 

#案例3:查詢城市名中第二個字符爲o的部門名和城市名(加篩選條件

SELECT 
  `department_name`,
  `city` 
FROM
  `departments` d,
  `locations` l 
WHERE d.`location_id` = l.`location_id`   -- 兩個篩選條件之間用  and進行連接
  AND l.`city` LIKE '_o%' 

#案例4:查詢每個城市的部門個數

SELECT 
  COUNT(*) 部門個數,
  city 城市 
FROM
  `locations` l,
  `departments` d 
  WHERE l.`location_id`=d.`location_id`
  GROUP BY l.`city`

#案例5:查詢有獎金的每個部門的部門名和部門的領導編號和該部門的最低工資

SELECT 
  d.`department_name`,
  d.`manager_id`,
  MIN(salary) 最低工資
FROM
  departments d,
  employees e 
WHERE d.`department_id` = e.`department_id` 
  AND e.`commission_pct` IS NOT NULL 
GROUP BY d.`department_name`

#案例6:查詢每個工種的工種號和員工的個數,並且按員工個數降序(排序

SELECT 
  j.`job_title` 工種名,
  COUNT(*) 員工個數 
FROM
  `employees` e,
  `jobs` j 
WHERE e.`job_id` = j.`job_id` 
GROUP BY j.`job_title`
ORDER BY 員工個數 DESC 

#案例7:查詢員工名、部門名和所在的城市(多表連接查詢)

SELECT 
  `last_name`,
  `department_name`,
  `city` 
FROM
  `departments` d,
  `employees` e,
  `locations` l 
WHERE d.`department_id` = e.`department_id` 
  AND d.`location_id` = l.`location_id` 

小結 

①多表等值連接的結果爲多表的交集部分

②n表連接,至少需要n-1個連接條件

③多表的順序沒有要求

④一般需要爲表起別名

⑤可以搭配前面介紹的所有子句使用,比如排序、分組、篩選

非等值連接 

 #案例:查詢員工的工資和工資級別並按薪資升序

SELECT 
  `salary`,
  `grade_level` 
FROM
  `employees` e,
  `job_grades` j 
WHERE e.`salary` BETWEEN j.`lowest_sal` 
  AND j.`highest_sal` 
ORDER BY e.`salary` 

自連接

意思也就是表自己連接自己

比如下表

#案例:查詢員工名和上級的名稱

思路:把這一個表看做一個員工表、一個領導表進行連接

select 
  e1.`last_name` 員工名,
  e2.`last_name` 領導名 
from
  `employees` e1,
  `employees` e2 
where e1.`manager_id` = e2.`employee_id` 

測試題

一、顯示員工表的最大工資,平均工資

SELECT 
  MAX(salary) 最大工資,
  AVG(salary) 平均工資 
FROM
  `employees` 

二、查詢員工表的employee_id,job_id,last_name,按department_id降序、salary升序

SELECT 
  `employee_id`,
  `job_id`,
  `last_name` 
FROM
  `employees` 
ORDER BY `department_id` DESC,
  `salary` ASC 

三、查詢員工表的job_id中包含'a和‘e’的,並且  a  在  e  的前面

SELECT 
  DISTINCT `job_id` 
FROM
  `employees` 
WHERE `job_id` LIKE '%a%e%' 

四、

已知表student,裏面有id(學號),name, gradeId(年級編號)

已知表grade,裏面有id(年級編號),name(年級號)

已知表result,裏面有id,score,studentNo(學號)

要求查詢姓名、年級名、成績

SELECT 
  s.`name`,
  g.`name`,
  r.`score` 
FROM
  student s,
  grade g,
  result r 
WHERE s.gradeId = g.id 
  AND s.id = r.studentId 

五、顯示當前日期、以及去前後空格、截取子字符串的函數

SELECT NOW();

SELECT TRIM(' ' FROM 'asfass  ');

SELECT SUBSTR(str,startIndex);

SELECT SUBSTR(str, startIndex, slength)

SQL練習

1、顯示所有的員工的姓名,部門號和部門名稱

SELECT 
  e.`last_name`,
  e.`department_id`,
  d.`department_name` 
FROM
  `employees` e,
  `departments` d 
WHERE e.`department_id` = d.`department_id` 

2、查詢90號部門員工的job_id和90號部門的location_id

SELECT 
  d.`department_id`,
  e.`job_id`,
  d.`location_id` 
FROM
  `employees` e,
  `departments` d 
WHERE e.`department_id` = d.`department_id` 
  AND e.`department_id` = 90 

3、選擇所有有獎金的員工的last_name,department_name,location_id,city

SELECT 
  e.`last_name`,
  d.`department_name`,
  l.`location_id`,
  e.`commission_pct`,
  l.`city` 
FROM
  `locations` l,
  `employees` e,
  `departments` d 
WHERE l.`location_id` = d.`location_id` 
  AND e.`department_id` = d.`department_id` 
  AND e.`commission_pct` IS NOT NULL 

4、選擇city在Toronto工作的員工的last_name,job_id, department_id, department_name,city

select 
  e.`last_name`,
  e.`job_id`,
  d.`department_id`,
  d.`department_name`,
  l.`city`
from
  `employees` e,
  `departments` d,
  `locations` l 
where e.`department_id` = d.`department_id` 
  and d.`location_id` = l.`location_id` 
  and l.`city` = 'Toronto' 

5、查詢每個工種、每個部門的部門名、工種名和最低工資

select 
  e.`job_id`,
  d.`department_name`,
  j.`job_title`, 
  min(salary) 最低工資 
from
  `employees` e,
  `departments` d,
  `jobs` j 
where e.`department_id` = d.`department_id` 
  and e.`job_id` = j.`job_id` 
group by e.`job_id` 

6、查詢每個國家下的部門個數大於2的國家的編號、部門號以及部門個數

SELECT 
  `country_id`,
  `department_id`,
  COUNT(*) 部門個數 
FROM
  `locations` l,
  `departments` d 
WHERE l.`location_id` = d.`location_id` 
GROUP BY l.`country_id` 
HAVING 部門個數 > 5

7、選擇指定員工的姓名、員工號,以及他的管理者的姓名和員工號,結果類似於下面的格式

employees         Emp#        manager       Mgr#

kochhar              101              king           100

SELECT 
  e1.`last_name` employees,
  e1.`employee_id` "emp#",
  e2.`last_name` manager,
  e2.`employee_id` "Mgr#" 
FROM
  `employees` e1,
  `employees` e2 
WHERE e1.`manager_id` = e2.`employee_id` 

sql99語法介紹

語法:

select  查詢列表

from  表1  別名 【連接類型】

join  表2  別名

on  連接條件

【where  篩選條件】

【group by 分組】

【having 篩選條件】

【order by  排序條件】

內連接(*):inner

外連接 :

                 左外(*):left 【outer】

                 右外(*):right 【outer】

                 全外:full【outer】

交叉連接 :cross

內連接

語法:

select  查詢列表 

from 表1 別名

inner  join  表2  別名

on  連接條件 

分類:  等值、非等值、自連接

等值連接 

#案例一:查詢員工名、部門名(調換表位置也可以)

SELECT 
  `last_name`,
  `department_name` 
FROM
  `employees` e 
  INNER JOIN `departments` d 
    ON e.`department_id` = d.`department_id` 

案例二、查詢名字中包含a的員工名和工種名(篩選

SELECT 
  `last_name`,
  `job_title` 
FROM
  `employees` e 
  INNER JOIN `jobs` j 
    ON e.`job_id` = j.`job_id`
WHERE e.`last_name` LIKE '%a%' 

 

案例三、查詢部門個數>3的城市名和部門個數(添加分組+篩選

思路:1、查詢每個城市的部門個數,2、在1結果上篩選滿足條件的

SELECT 
  `city`,
  COUNT(*) 
FROM
  `locations` l 
  INNER JOIN `departments` d 
    ON l.`location_id` = d.`location_id` 
GROUP BY city 
HAVING COUNT(*) > 3 

案例四、查詢哪個部門的部門員工個數>3的部門名和員工個數,並按個數降序

SELECT 
  d.`department_name`,
  COUNT(*) 
FROM
  `employees` e 
  INNER JOIN `departments` d 
    ON e.`department_id` = d.`department_id` 
GROUP BY e.`department_id` 
HAVING COUNT(*) > 3 
ORDER BY COUNT(*) DESC 

案例五、查詢員工名、部門號、工種名,並按部門號降序(多變內聯)

SELECT 
  `last_name`,
  d.`department_name`,
  `job_title` 
FROM
  `employees` e 
  INNER JOIN `departments` d 
    ON e.`department_id` = d.`department_id` 
  INNER JOIN `jobs` j 
    ON e.`job_id` = j.`job_id` 
ORDER BY e.`department_id` DESC 

非等值連接

案例: 查詢員工的工資級別

SELECT 
  `salary`,
  `grade_level` 
FROM
  `employees` e 
  INNER JOIN `job_grades` j 
    ON salary BETWEEN `lowest_sal` 
    AND `highest_sal` 

案例2:查詢每個工資級別大於20的個數,並且按工資級別降序

SELECT 
  `grade_level`,
  COUNT(*) 級別個數 
FROM
  `employees` e 
  INNER JOIN `job_grades` j 
    ON salary BETWEEN `lowest_sal` 
    AND `highest_sal` 
    GROUP BY grade_level
    HAVING 級別個數 > 20
    ORDER BY COUNT(*) DESC

 

自連接 

案例:查詢員工的姓名、上級的名字

SELECT 
  e1.`last_name`員工,
  e2.`last_name` 上級
FROM
  `employees` e1 
  INNER JOIN `employees` e2 
    ON e1.`manager_id` = e2.`employee_id` 

案例2:查詢姓名中包含字符k的員工的姓名、上級的名字

SELECT 
  e1.`last_name` 員工,
  e2.`last_name` 上級 
FROM
  `employees` e1 
  INNER JOIN `employees` e2 
    ON e1.`manager_id` = e2.`employee_id` 
WHERE e1.`last_name` LIKE '%k%' 

左右連接

應用場景:用於查詢一個表中有,另外一個表中沒有的記錄

特點:

1、

外連接的查詢結果爲主表中的所有記錄

如果從表中有和他匹配的,則顯示匹配的值,

如果從表中沒有和他匹配的,則顯示null

外連接查詢結果=內連接結果+主表中有而從表中沒有的記錄

2、左外連接:left join左邊的是主表    右外連接:right join右邊的是主表

3、左外和右外交換兩個表的順序,可以實現同樣的效果

4、全連接=內連接的結果+表1中有但表2沒有的+表2有但是表1沒有的

SELECT 
  bo.*,
  b.* 
FROM
  `boys` bo
  LEFT OUTER JOIN `beauty` b 
 ON bo.`id`=b.`boyfriend_id`

引入:查詢男朋友不在男神表的女神名 

SELECT 
  b.`name`
FROM
  `beauty` b 
  LEFT OUTER JOIN `boys` bo 
    ON b.`boyfriend_id` = bo.`id` 
WHERE bo.`id` IS NULL 

案例:查詢哪個部門沒有員工

左連接之後,查詢員工id爲null的,另外

SELECT 
  d.* 
FROM
  `departments` d 
  LEFT OUTER JOIN `employees` e 
    ON d.`department_id` = e.`department_id` 
WHERE e.`email` IS NULL 

全外連接

MySQL不支持全外連接 

交叉連接

也就是表之間的笛卡爾積 

SELECT 
  b.*,
  bo.* 
FROM
  `boys` b 
  CROSS JOIN `beauty` bo 

查詢總結

案例講解

 一、查詢編號>3的女神編號、名字以及男朋友的信息,如果有則列出詳細信息,如果沒有,用null填充

SELECT 
  b.`id`,
  b.`name`,
  bo.* 
FROM
  `beauty` b 
  LEFT OUTER JOIN `boys` bo 
    ON b.`boyfriend_id` = bo.`id` 
    WHERE b.`id`>3

二、查詢哪個城市沒有部門

SELECT 
  l.*,d.* 
FROM
  `locations` l 
  LEFT OUTER JOIN `departments` d 
    ON l.`location_id` = d.`location_id` 
    WHERE d.`department_id` IS NULL

三、查詢部門名爲SAL或IT的員工信息

SELECT 
  e.*, d.`department_name`, d.`department_id`
FROM
  `employees` e 
  RIGHT OUTER JOIN `departments` d 
    ON e.`department_id` = d.`department_id` 
WHERE d.`department_name` IN('SAL', 'IT')

注:有重名部門的情況,內連接的話,少兩條null的信息,就是這個部門沒有員工

子查詢 

含義:出現在其他語句中的select語句,稱之爲子查詢或內查詢

外部的查詢語句,稱之爲主查詢或外查詢

where和having後面的子查詢

特點:

①子查詢放在小括號內

②子查詢一般放在條件的右側

③標量子查詢,一般搭配着單行操作符使用 >  <  >=  <=  =  <>

列子查詢,一般搭配着多行操作符使用    in   、any/some、 all

④子查詢的執行優先於主查詢執行,主查詢的條件用到了子查詢的結果

標量子查詢

案例1:誰的工資比Abel高?

①查詢Abel的工資

②查詢員工薪資>①的

select 
  `employee_id`,
  `last_name`,
  salary 薪資 
from
  `employees` 
where salary > 
  (select 
    salary 
  from
    `employees` 
  where `last_name` = 'Abel')

 

案例2:返回job_id與141號員工相同,salary比143號員工多的員工  姓名,job_id 和 工資

思路:先子查詢的單行單列值,然後再進行

SELECT 
  `last_name`,
  `job_id`,
  `salary` 
FROM
  `employees` 
WHERE job_id = 
  (SELECT 
    job_id 
  FROM
    `employees` 
  WHERE `employee_id` = 141) 
  AND salary > 
  (SELECT 
    salary 
  FROM
    `employees` 
  WHERE `employee_id` = 143)

案例3:返回公司工資最少的員工的last_name,job_id和salary

select 
  `last_name`,
  `job_id`,
  `salary` 
from
  `employees` 
where salary = 
  (select 
    min(salary) 
  from
    `employees`)

案例4:查詢最低工資大於50號部門最低工資的部門id和其最低工資

思路:

①查詢50號部門最低工資

②查詢各個部門的最低工資

③查詢各個部門的最低工資 > ①的的部門id和其最低工資

SELECT 
  MIN(salary) 最低工資,
  department_id 
FROM
  `employees` 
GROUP BY `department_id` 
HAVING 最低工資 > 
  (SELECT 
    MIN(salary) 
  FROM
    `employees` 
  WHERE `department_id` = 50)

列子查詢(多行子查詢)

案例一、返回location_id是1400或1700的部門中的所有員工姓名 

SELECT 
  `last_name` 
FROM
  `employees` 
WHERE `department_id` IN 
  (SELECT 
    `department_id` 
  FROM
    `departments` 
  WHERE `location_id` IN (1700, 1400))

 

此題也可以使用內連接:

SELECT 
  `last_name` 
FROM
  `employees` e 
  INNER JOIN `departments` d 
WHERE e.`department_id` = d.`department_id` 
  AND d.`location_id` IN (1700, 1400)

案例2:返回其他部門中比job_id爲‘IT_PROG’部門任一工資低的員工號、姓名、job_id以及salary 

注:比X部門任一工資低:小於X部們的任何一個就OK,所以用any關鍵字就OK

SELECT 
  `employee_id` 員工號,
  `last_name` 姓名,
  `job_id`,
  `salary` 
FROM
  `employees` 
WHERE salary < ANY 
  (SELECT DISTINCT 
    salary
  FROM
    `employees` 
  WHERE job_id = 'IT_PROG')
  AND job_id <> 'IT_PROG'

 案例3:返回其他部門中比job_id爲‘IT_PROG’部門所有工資都低的員工的  員工號、姓名、job_id  以及salary

注:任一,所以使用ALL關鍵字

SELECT 
  `employee_id` 員工號,
  `last_name` 姓名,
  `job_id`,
  `salary` 
FROM
  `employees` 
WHERE salary < ALL 
  (SELECT DISTINCT 
    salary
  FROM
    `employees` 
  WHERE job_id = 'IT_PROG')
  AND job_id <> 'IT_PROG'

-- 或者 --

SELECT 
  `employee_id` 員工號,
  `last_name` 姓名,
  `job_id`,
  `salary` 
FROM
  `employees` 
WHERE salary < 
  (SELECT DISTINCT 
    MIN(salary) 
  FROM
    `employees` 
  WHERE job_id = 'IT_PROG') 
  AND job_id <> 'IT_PROG' 

 

行子查詢

...

exits後面的子查詢(相關子查詢)

語法:

exists(完整的查詢語句)

結果:

1或0

 案例1:查詢員工名和部門名

select 
  `department_name` 
from
  `departments` d 
where exists ( -- 存在,
    select*
from
  `employees` e 
where d.`department_id` =e.`department_id` -- 部門編號在員工表中有對應的存在
)

用 in的話

SELECT 
  `department_name` 
FROM
  `departments` d 
WHERE d.`department_id` IN 
  (SELECT DISTINCT 
    `department_id` 
  FROM
    `employees`)

#案例:查詢沒有女朋友的男神信息

使用exists

SELECT 
  bo.* 
FROM
  `boys` bo 
WHERE NOT EXISTS 
  (SELECT 
    * 
  FROM
    `beauty` b 
  WHERE b.`boyfriend_id` = bo.`id`)

使用   in

SELECT 
  bo.* 
FROM
  `boys` bo
WHERE bo.`id` NOT IN
  (SELECT DISTINCT 
    boyfriend_id 
  FROM
    `beauty`)

案例

#1、查詢和zlotkey相同部門的員工姓名和工資

SELECT 
  `last_name`,
  `salary` 
FROM
  `employees` 
WHERE `department_id` = 
  (SELECT 
    `department_id` 
  FROM
    `employees` 
  WHERE `last_name` = 'zlotkey')

#2、查詢工資比公司平均工資高的員工的員工號、姓名和工資

SELECT 
  `employee_id`,
  `last_name`,
  `salary`
FROM
  `employees` 
WHERE salary > 
  (SELECT 
    AVG(salary) 
  FROM
    `employees`)

#3、查詢各部門中工資比本部門平均工資高的員工的員工號、姓名和工資

-- 方法一:
SELECT 
  `employee_id`,
  `last_name`,
  `salary` 
FROM
  `employees` e1 
WHERE salary > 
  (SELECT 
    AVG(salary) AVG,
    department_id 
  FROM
    `employees` e2 
  WHERE e2.`department_id` = e1.`department_id`) 
  


-- 方法二:
SELECT 
  `employee_id`,
  `last_name`,
  `salary` 
FROM
  `employees` e 
  INNER JOIN 
    (SELECT 
      AVG(salary) ag,
      department_id 
    FROM
      `employees` 
    GROUP BY department_id) ag_dep 
    ON e.`department_id` = ag_dep.`department_id` 
WHERE e.`salary` > ag_dep.ag 

#4、查詢和姓名中包含字母u的員工在相同部門的員工的員工號和姓名

SELECT 
  `employee_id`,
  `last_name` 
FROM
  `employees` 
WHERE `department_id` IN 
  (SELECT DISTINCT
    `department_id` 
  FROM
    `employees` 
  WHERE `last_name` LIKE '%u%')

#5、查詢在部門的location_id爲1700的部門工作的員工的員工號

SELECT 
  `employee_id` 
FROM
  `employees` 
WHERE `department_id` = ANY   -- 或者 in
  (SELECT 
    `department_id` 
  FROM
    `departments` 
  WHERE `location_id` = 1700)

#6、查詢管理者是K_ing的員工姓名和工資

SELECT 
  `last_name`,
  `salary` 
FROM
  `employees` 
WHERE `manager_id` IN 
  (SELECT 
    `employee_id` 
  FROM
    `employees` 
  WHERE `last_name` LIKE 'k_ing')

#7、查詢工資最高的員工的姓名,要求first_name和last_name顯示爲一列,列名爲姓.名

SELECT 
  CONCAT(`first_name`, '.', `last_name`) '姓.名' 
FROM
  `employees` 
WHERE salary = 
  (SELECT 
    MAX(salary) 
  FROM
    `employees`)

總結:對於子查詢來說,,SQL書寫步驟可以爲:先寫子SQL語句,再寫主查詢

分頁查詢

應用場景:當要顯示的數據,一頁顯示不全,需要分頁提交SQL請求

語法:

select   查詢列表

from   表

【join  type   join  表2

on   連接條件

where   篩選條件

group  by 分組字段

having  分組後的篩選

order   by   排序的字段】 

limit  offset, size

offset要顯示條目的起始索引(起始索引從0開始

案例一:查詢前5條員工信息

SELECT 
  * 
FROM
  `employees` 
LIMIT 0, 5 

案例二:查詢第11條到第25條

SELECT 
  * 
FROM
  `employees` 
LIMIT 10, 15 

 案例三:有獎金的員工的信息,並且工資較高的前10名顯示出來

SELECT 
  * 
FROM
  `employees` 
WHERE `commission_pct` IS NOT NULL 
ORDER BY salary DESC
LIMIT 0, 10 

特點

①limit語句放在查詢語句的最後

②公式

要顯示的頁數page,每頁的條目數size

select *  from  表  limit  (page-1)*size, size

測試題

一、查詢所有學員的郵箱的用戶名(注:郵箱中@前面的字符)

select 
  substr(email, 1, instr(email, '@') - 1) 用戶名 -- instr,獲取字符的索引,substr,從指定索引開始截取指定長度的字符串
from
  stuinfo 

二、查詢男生和女生的個數

SELECT 
  COUNT(*) 個數, sex 
FROM
  stuinfo 
GROUP BY sex 

三、查詢年齡>18歲的所有學生的姓名和年級名稱

SELECT 
  `name`,
  gradeName 
FROM
  stuinfo s
  INNER JOIN grade g
  ON s.gradeId = g.id
  WHERE s.age > 18

四、查詢哪個年級的學生的最小年齡>20歲

SELECT 
      MIN(age),
      gradeId 
    FROM
      stuinfo 
    GROUP BY gradeId 
    HAVING MIN(age) > 20

五、試說出查詢語句中涉及到的所有的關鍵字,以及執行先後順序

select   查詢列表                         ⑦

from  表                                       

連接類型  join  表2                      

on   連接條件                               

where   篩選條件                         

group  by  分組列表                   

having  分組後的篩選                 

order  by   排序列表                    

limit  起始索引, 條目數              

子查詢經典案例

#1、查詢工資最低的員工信息:last_name, salary 

select 
  `last_name`,
  `salary` 
from
  `employees` 
where salary = 
  (SELECT 
    MIN(salary) 
  FROM
    `employees`)

#2、查詢平均工資最低的部門信息(@@)

SELECT 
  * 
FROM
  `departments` 
WHERE `department_id` = 
  (SELECT 
    department_id 
  FROM
    `employees` 
  GROUP BY `department_id` 
  ORDER BY AVG(salary) 
  LIMIT 1)

                                                                                        #3、查詢平均工資最低的部門信息和該部門的平均工資

SELECT 
  d.*, af.ag 平均薪資 
FROM
  `departments` d 
  INNER JOIN 
    (SELECT 
      AVG(salary) ag,
      `department_id` 
    FROM
      `employees` 
    GROUP BY `department_id` 
    ORDER BY ag 
    LIMIT 1) AS af 
    ON d.`department_id` = af.department_id 

#4、查詢平均工資最高的job信息

SELECT 
  j.* 
FROM
  `jobs` j 
WHERE `job_id` = 
  (SELECT   -- 等於最高平均工資的job_id
    `job_id` 
  FROM
    `employees` 
  GROUP BY `job_id` 
  HAVING AVG(salary) = 
    (SELECT 
      AVG(salary) ag 
    FROM
      `employees` 
    GROUP BY `job_id` 
    ORDER BY ag DESC 
    LIMIT 1)) -- 最高平均工資
   

#5、查詢平均工資高於公司平均工資的部門有哪些

		

SELECT 
  AVG(salary) 平均薪資,
  `department_id` 部門號 
FROM
  `employees` 
  GROUP BY `department_id`
HAVING AVG(salary) > 
  (SELECT 
    AVG(salary) 
  FROM
    `employees`) -- 公司的平均工資
   

 

#6、查詢出公司中所有manager的詳細信息

SELECT 
  e1.* 
FROM
  `employees` e1 
WHERE e1.`department_id` IN 
  (SELECT DISTINCT 
    `manager_id` 
  FROM
    `employees` e2)

#7、各個部門中最高工資中最低的那個部門的最低工資是多少

SELECT 
   * 
FROM
  `employees` 
WHERE `employee_id` IN
  (SELECT DISTINCT 
    `manager_id` 
  FROM
    `employees`)

 #8、查詢平均工資最高的部門的manager的詳細信息:last_name,department_id,email,salary

select 
  `last_name`,
  `department_id`,
  `email`,
  `salary` 
from
  `employees` 
where `employee_id` = 
  (SELECT 
    `manager_id` 
  FROM
    `departments` 
  WHERE `department_id` = 
    (SELECT 
      department_id 
    FROM
      `employees` 
    GROUP BY `department_id` 
    ORDER BY AVG(salary) DESC 
    LIMIT 1)) -- 各部門平均薪資最高的部門id))
   

七、聯合查詢 

union  聯合  合併:將多條查詢語句的結果合併成一個結果,支持多個union

 引入的案例:查詢部門編號>90或郵箱包含a的員工信息

select * from `employees` where email like '%a%'
union
SELECT * FROM `employees` WHERE `department_id`>90

 應用場景:要查詢的結果來自多個表,且多個表沒有直接的聯繫關係

特點:

①要求多條查詢語句的查詢列數是一致的

②要求多條查詢語句的查詢的每一列的類型和順序最好一致

③union關鍵字默認去重,可以使用union  all不去重

查詢的爲兩個表的並集,重複項會被去重,如果不想去重,可以使用  union  all關鍵字

 

 

 

 

 

 

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

           

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章