1. 程式人生 > 其它 >SQL / 資料查詢語言DQL(Data Query Language )

SQL / 資料查詢語言DQL(Data Query Language )

  1、基礎查詢

#進階1:基礎查詢
/*
語法:
select 查詢列表 from 表名;
1、查詢列表可以是:表中的欄位、常量值、表示式、函式
2、查詢的結果是一個虛擬的表格 ( 不儲存 )
*/

#開啟資料庫
USE myemployees;

#1、查詢表中的單個欄位
SELECT last_name FROM employees;

#2、查詢表中的多個欄位
SELECT last_name,salary,email FROM employees;

#3、查詢表中的所有欄位
 
#方式一( 欄位,雙擊欄位可以快速新增,選中程式碼,按F12格式化或按F9執行 ):
SELECT 
  `first_name`, # 欄位兩邊的著重號`是區分是關鍵字還是欄位的,可以去掉,
  `last_name`,
  `email`,
  `phone_number`,
  `job_id`,
  `salary`,
  `commission_pct`,
  `manager_id`,
  `department_id`,
  `hiredate` 
FROM employees ; # 方式二,* 代表所有欄位,欄位與原始表一樣: SELECT * FROM employees; #4、查詢常量值 SELECT 100; SELECT 'john'; #查詢字元常量 #5、查詢表示式 SELECT 100*98; #6、查詢函式 SELECT VERSION(); #查詢函式VERSION()的返回值 #7、起別名 /* 便於理解(提高可讀性) 如果要查詢的欄位有重名的使用別名可以區分開來 */ #方式一:使用as SELECT 100%98 AS 結果; SELECT last_name AS 姓, first_name ASFROM
employees; #方式二:使用空格 SELECT last_name 姓, first_name 名 FROM employees; #別名含有特殊符號的要加雙引號或單引號 SELECT salary AS "out put" FROM employees; #8、去重 #查詢員工表中涉及的所有的部門編號 ( 去掉重複的編號用distinct ) SELECT DISTINCT department_id FROM employees; #9+號的作用 /* java中的+號: 運算子,兩個運算元都為數值型 連線符,只要一個運算元為字串 mysql中的+號: 運算子,僅僅只有一個功能 select 100+90; #兩個運算元都為數值型,則做加法運算 select '123'+90; #只要其中一個運算元為字元型,試圖把字元型轉為數值型, #轉換成功則繼續做加法運算 select 'john'+90; #轉換失敗則字元型數值為0,再做加法運算 select null+90; #只要其中一個運算元為null,結果為null
*/ #查詢員工名和姓連線成一個欄位並顯示為姓名,使用字元連線函式concat(), #只要其中一個運算元為null,結果為null SELECT CONCAT(last_name, ' ', first_name) AS 姓名 FROM employees ; #使用ifnull()函式,避免結果為null SELECT IFNULL(`commission_pct`, 0) AS 獎金率, `commission_pct` FROM employees ; SELECT CONCAT( `first_name`, ',', `last_name`, ',', `email`, ',', IFNULL(`commission_pct`, 0) ) AS out_put FROM employees ;
View Code

  2、條件查詢

#進階2:條件查詢
/*
語法:( 執行順序 from/where/select )
    select
        查詢列表
    from
        表名
    where
        篩選條件(結果是true或false);
分類:
    一、按條件表示式篩選
        條件運算子:
            > < = != <> >= <= <=>
        其中 <> 與 != 相同,<=> 安全等於
    二、按邏輯表示式篩選 ( 作用:是連線條件表示式的 )
        邏輯運算子:
            && || !
            and or not
    三、模糊查詢
        like
        between and
        in
        is null|is not null
*/

USE myemployees;
#一、按條件表示式篩選

#查詢工資>12000的員工的資訊
SELECT 
  * 
FROM
  employees 
WHERE salary > 12000 ;

#查詢部門編號不等於90號的員工名和部門編號
SELECT 
  first_name,
  department_id 
FROM
  employees 
WHERE department_id <> 90 ;

#二、按邏輯表示式篩選

#查詢工資在10000到20000之間的員工名、工資及獎金
SELECT 
  first_name,
  salary,
  commission_pct 
FROM
  employees 
WHERE salary >= 10000 
  AND salary <= 20000 ;

#查詢部門編號不是在90到110之間 或 工資高於15000的員工資訊
/*
select 
  * 
from employees
where department_id <90 
    or department_id > 110
  or salary > 15000 ;
*/
SELECT 
  * 
FROM
  employees 
WHERE NOT (
    department_id >= 90 
    AND department_id <= 110
  ) 
  OR salary > 15000 ;

#模糊查詢
/*
like
一般和萬用字元搭配使用
    萬用字元:
    %任意多個字元包含0個字元
    _任意單個字元
between and
in
is null|is not null
*/

#查詢員工中包含字元a的員工資訊
SELECT 
  * 
FROM
  employees 
WHERE first_name LIKE '%a%' ;

#查詢員工中第三個字元為e,第五個字元為a的員工和工資
SELECT 
  first_name,
  salary 
FROM
  employees 
WHERE first_name LIKE '__e_a%' ;

#查詢員工姓名中第二個字元為_的員工姓名
/*select 
  last_name 
from
  employees 
where last_name like '_\_%' ; #使用轉義字元\
*/

SELECT 
  last_name 
FROM
  employees 
WHERE last_name LIKE '_$_%' ESCAPE '$' ; # ESCAPE 定義轉義字元
#查詢員工編號在100到120之間的員工資訊
SELECT 
  * 
FROM
  employees 
WHERE employee_id >= 100 
  AND employee_id <= 120 ;
  
#查詢員工部門號第一個數字為1的員工資訊,like 可以查詢數值型的欄位
SELECT 
  * 
FROM
  employees 
WHERE department_id LIKE '1__' ;
 
#between and 提高語句簡潔度,包含臨界值如下的100 120,兩個臨界值不調換順序
SELECT 
  * 
FROM
  employees 
WHERE employee_id BETWEEN 100 
  AND 120 ;

#查詢員工的工種編號是 IT_PROG、AD_VP、AD_PRES中的一個員工名和工種編號
SELECT 
  first_name,
  job_id 
FROM
  employees 
WHERE job_id = 'IT_PROT' 
  OR job_id = 'AD_VP' 
  OR job_id = 'AD_PRES' ;

#IN 判斷某個欄位的值是否屬於in列表中的某一項
#比使用or提高語句簡潔度,in類別的值型別必須一致或相容,不支援萬用字元
SELECT 
  first_name,
  job_id 
FROM
  employees 
WHERE job_id IN ('IT_PROT', 'AD_VP', 'AD_PRES') ;

#查詢沒有獎金的員工名和獎金率
/*
= 或 <> 不能判斷 null
is null或is not null 可以判斷null值
*/
SELECT 
  first_name,
  commission_pct 
FROM
  employees 
WHERE commission_pct IS NULL ; # 沒有獎金 WHERE commission_pct IS NOT NULL ;

#安全等於 <=> ,可讀性不好
SELECT 
  first_name,
  commission_pct 
FROM
  employees 
WHERE commission_pct <=> NULL ; #is null

#獎金等於12000的員工名
SELECT 
  first_name,
  salary
FROM
  employees 
WHERE salary <=> 12000 ;

# is null 僅僅可以判斷null值,可讀性高,建議使用
# <=> 即可以判斷null值,又可以判斷普通的數值,可讀性較低

#查詢員工號為176的員工的姓名和部門和年薪
SELECT 
  first_name,
  department_id,
  salary * 12 *(1+ IFNULL(commission_pct, 0)) AS 年薪 
FROM
  employees 
WHERE employee_id = 176 ;

#查詢沒有獎金,且工資小於18000的salary,last_name
SELECT 
  last_name,
  salary 
FROM
  employees 
WHERE commission_pct IS NULL 
  AND salary < 18000 ;

#查詢 employee 表中,job_id 不為 'IT' 或者 工資為12000的員工的資訊
SELECT 
  * 
FROM
  employees 
WHERE job_id <> 'IT' 
  OR salary = 12000 ;

#檢視部門 departments 表的結構
DESC departments;

#檢視部門departments表中涉及到了哪些位置編號
 
SELECT DISTINCT  #distinct 去重
  location_id 
FROM
  departments ;

#------------------------
SELECT 
  * 
FROM
  employees ;

#如果判斷的欄位有null值下面語句與上面語句不一樣
SELECT 
  * 
FROM
  employees 
WHERE commission_pct LIKE '%%' 
  AND last_name LIKE '%%' ;
View Code

  3、排序查詢

#進階3:排序查詢
/*
語法:
    select 查詢列表
    from 表
    【where 篩選條件】
    order by 排序列表 【asc|desc】
特點:
    1、asc是升序,desc是降序
        如果不寫,預設是升序
    2、order by 子句中可以支援單個欄位、多個欄位、表示式、函式、別名
    3、order by 子句一般放在查詢語句的最後面,limit子句除外
*/
#查詢員工資訊,要求工資從高到低排序
SELECT 
  * 
FROM
  employees 
ORDER BY salary DESC ;

#查詢部門編號 >= 90的員工資訊,按入職時間的先後進行排序 【 新增篩選條件 】
SELECT 
  * 
FROM
  employees 
WHERE department_id >= 90 
ORDER BY hiredate ;

#按年薪的高低顯示員工的資訊和年薪【 按表示式排序 】
SELECT 
  *,
  salary * 12 * (1 + IFNULL(commission_pct, 0)) AS 年薪 
FROM
  employees 
ORDER BY salary * 12 * (1 + IFNULL(commission_pct, 0)) DESC;

#按年薪的高低顯示員工的資訊和年薪【 按別名排序 】
SELECT 
  *,
  salary * 12 * (1 + IFNULL(commission_pct, 0)) AS 年薪 
FROM
  employees 
ORDER BY 年薪 DESC;

#按姓名的長度顯示員工的姓名和工資【按函式排序】
SELECT 
  LENGTH(last_name) AS 位元組長度,
  last_name,
  salary 
FROM
  employees 
ORDER BY LENGTH(last_name) DESC ;

#查詢員工資訊,要求先按工資升序排序,再按員工編號降序排序【按多個欄位排序】
SELECT 
  * 
FROM
  employees 
ORDER BY salary ASC,
  employee_id DESC ;

#查詢員工的姓名和部門號和年薪,按年薪降序 按姓名升序
SELECT 
  last_name,
  department_id,
  salary * 12 * (1 + IFNULL(commission_pct, 0)) AS 年薪 
FROM
  employees 
ORDER BY 年薪 DESC,
  last_name ASC ;

#選擇工資不在8000到17000的員工的姓名和工資,按工資降序
SELECT 
  last_name,
  salary 
FROM
  employees 
WHERE salary NOT BETWEEN 8000 
  AND 17000 
ORDER BY salary ASC ;

#查詢郵箱中包含e的員工資訊,並先按郵箱的位元組數降序,再按部門號升序
SELECT 
  * 
FROM
  employees 
WHERE email LIKE '%e%' 
ORDER BY LENGTH(email) DESC,
  department_id ASC ;
View Code

  4、函式查詢

#進階4:常見函式
/*

概念:類似於Java的方法,將一組邏輯語句封裝在方法體中,對外暴露方法名
好處:1、隱藏了實現細節 2、提高程式碼的重用性
呼叫:select 函式名(實參列表) 【from 表】;
特點:叫什麼(函式)、幹什麼(函式功能)
分類:  1、單行函式,如concat、length、ifnull等
    字元函式、數學函式、日期函式、其他函式、流程控制函式  
    2、分組函式
    功能:做統計使用,又稱為統計函式、聚合函式、組函式
常見函式:
    一、單行函式
    字元函式:
    length concat substr instr trim upper lower lpad rpad replace
    數學函式:
    round ceil floor truncate mod
    日期函式:
    now curdate curtime year month monthname day hour minute sencond str_to_date date_format
    其他函式:
    version database user
    控制函式:
    if case
    二、分組函式
    
    
*/
#單行函式
#一、字元函式
#length 獲取引數值的位元組個數
SELECT LENGTH('john');
SELECT LENGTH('張三丰hahaha'); #一個漢字3個位元組,結果為15

SHOW VARIABLES LIKE '%char%'; #utf8

#concat 拼接字串
SELECT CONCAT(last_name,'_',first_name) 姓名 FROM employees;

#upperlower
SELECT UPPER('john');
SELECT LOWER('JOHN');

#將姓變大寫,名變小寫,然後拼接
SELECT CONCAT(LOWER(first_name),'_',UPPER(last_name)) 姓名 FROM employees;

#substr substring 擷取字元 索引從1開始
SELECT SUBSTR('李莫愁愛上了陸展元',7) out_put;
SELECT SUBSTR('李莫愁愛上了陸展元',1,3) out_put; #1是開始索引,3是字元長度
SELECT SUBSTR('limochouaishangleluzhanyuan',7);

#姓名中首字元大寫,其他字元小寫然後用_拼接,顯示出來
SELECT CONCAT(UPPER(SUBSTR(last_name,1,1)),'_',SUBSTR(last_name,2)) AS 姓名 FROM employees;

#instr 返回子串第一次出現的索引,如果找不到,返回0
SELECT INSTR('楊不悔','不悔'); #返回值,是首次適配的索引值

#trim 去除首尾字元
SELECT LENGTH(TRIM('     張翠山    ')) AS out_put;
SELECT TRIM('a' FROM 'aaaaa張aa翠山aaaa') AS out_put;

#lpad 左填充 不夠長度從左邊填充字元 長度低於字元個數會截斷字串
SELECT LPAD('殷素素',10,'*') AS out_put;

#rpad 右填充
SELECT RPAD('殷素素',10,'*') AS out_put;

#replace 替換
SELECT REPLACE('Hello World Hello','Hello','tt') AS out_put;

#二、數學函式

#round 四捨五入
SELECT ROUND(1.657);
SELECT ROUND(1.657,2); #保留小數點後2位

#ceil 向上取整,返回 >= 該引數的最小整數
SELECT CEIL(1.003);

#floor 向下取整,返回 <= 該引數的最小整數
SELECT FLOOR(9.99);  # 9
SELECT FLOOR(-9.99); # -10

#truncate 截斷
SELECT TRUNCATE(1.6999,1); # 1.6

#mod 取餘 a-a/b*b
SELECT MOD(10,3); # 1
SELECT -10%3;

#三、日期函式

#now 返回當前系統日期+時間
SELECT NOW();

#curdate 返回當前系統日期,不包含時間
SELECT CURDATE();

#curtime 返回當前系統時間,不包含日期
SELECT CURTIME();

#------------------------
SELECT CURDATE(),CURTIME();

#可以獲取指定的部分,年,月,日,小時,分鐘,秒
SELECT YEAR(NOW());
SELECT YEAR('1998-1-1');
SELECT YEAR('1998/1/1');
SELECT YEAR('1998.1.1');
SELECT YEAR(hiredate) ASFROM employees;

SELECT MONTH(NOW());
SELECT MONTH('1998.1.1');
SELECT MONTHNAME(NOW());  #顯示英文月名 monthname

SELECT DAY(NOW()); #day

SELECT MINUTE(NOW()); # minute

SELECT HOUR(NOW());

SELECT SECOND(NOW());

#str_to_date 將日期格式的字元轉換成指定格式的日期,解析失敗返回 null
#%Y四位年份 %y二位年份 %m補0的月份 %c月份 %d日 %H 24小時制 %h 12小時制 %i分鐘 %s秒
SELECT STR_TO_DATE('7.22.2021','%m.%d.%Y'); #前後格式一致、正確

#date_format: 將日期轉換成字元 轉換失敗返回 null
SELECT DATE_FORMAT('2021.7.22','%Y年%m月%d日');

#查詢入職日期為1992-4-3的員工資訊
SELECT * FROM employees WHERE hiredate = '1992-4-3';
SELECT * FROM employees WHERE hiredate = STR_TO_DATE('4-3 1992','%c-%d %Y');

#查詢有獎金的員工名和入職日期(XX月/XX日 XX年)
SELECT last_name, DATE_FORMAT(hiredate,'%m月/%d日 %y年') AS 入職日期 FROM employees WHERE commission_pct IS NOT NULL;

#四、其他函式

SELECT VERSION();
SELECT    DATABASE(); #檢視當前庫
SELECT USER();

#五、流程控制函式

#if函式: if else 的效果

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

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

#case函式 方式一:switch case的效果
/*
Java中:
switch(變數或表示式){
    case 常量1:語句1;break;
    ...
    default: 語句n; break;
}

mysql中
case 要判斷的欄位或表示式    #case相當於Java的switch
when 常量1 then 要顯示的值1或語句1   #when相當於Java的case
...
else 要顯示的值n或語句n      #相當於Java的default
end               #結束標誌

*/

/*查詢員工的工資,要求
部門號=30,顯示的工資為1.1倍
部門號=40,顯示的工資為1.2倍
部門號=50,顯示的工資為1.3倍
其他部門,顯示的工資為原工資

*/

SELECT salary AS 原始工資, department_id,
CASE department_id
WHEN 30 THEN salary * 1.1  #值不是語句
WHEN 40 THEN salary * 1.2
WHEN 50 THEN salary *1.3
ELSE salary
END AS 新工資
FROM employees;

#case函式 方式二:類似於 多重if
/*
Java中:
if(條件1){
    語句1:
}else if(條件2){
    語句2:
}
...
else{
    語句n:
    
}

sql中:
case
when 條件1 then 要顯示的值1或語句1
...
else 要顯示的值n或語句n
end
*/

/*查詢員工的工資情況
如果工資 > 20000,顯示A級別
如果工資 >15000,顯示B級別
如果工資 >10000,顯示C級別
否則,顯示D級別
*/

SELECT salary,  # 顯示salay,後面還有顯示加逗號
CASE
WHEN salary > 20000 THEN 'A'  # 值1 'A'
WHEN salary > 15000 THEN 'B'
WHEN salary > 10000 THEN 'C'
ELSE 'D'
END AS 工資級別  # 顯示 工資級別
FROM employees;

#顯示系統時間(注:日期+時間)
SELECT NOW();

#查詢員工號,姓名,工資,以及工資提高百分之20後的結果(new salary)
SELECT employee_id, last_name, salary,salary * 1.20 AS 'new salary'
FROM employees;

#將員工的姓名按首字母排序,並寫出姓名的長度(length)
SELECT LENGTH(last_name) AS 'LENGTH', SUBSTR(last_name,1,1) AS 首字元, last_name FROM employees ORDER BY 首字元 ASC;

#做一個查詢,產生下面結果 Dream Salary King earns 24000 monthly but wants 72000   #用到拼接 concat
SELECT 
  CONCAT(
    last_name,
    ' earns ',
    salary,
    ' monthly but wants ',
    salary * 3
  ) AS 'Dream Salary' 
FROM
  employees 
WHERE salary = 24000 ;

#使用case-when   方式一:
SELECT last_name, job_id AS job,
CASE job_id 
WHEN 'AD_PRES' THEN 'A'
WHEN 'ST_MAN' THEN 'B'
WHEN 'IT_PROG' THEN 'C'
WHEN 'SA_PRE' THEN 'D'
WHEN 'ST_CLEAK' THEN 'E'
END AS grade
FROM employees
WHERE job_id = 'AD_PRES';

#分組函式
/*
功能:用作統計使用,又稱為聚合函式或統計函式或組函式

分類:
sum 求和、 avg 平均值、max 最大值、min 最小值、count 計算個數(非空值)

特點:
1、sum、avg一般用於處理數值型
   max、min、count可以處理任何型別
2、以上分組函式都忽略null值
3、可以和distinct搭配實現去重的運算
4、count 詳細介紹
   一般使用 COUNT(*) 用於統計行數
5、和分組函式一同查詢的欄位要求是group by 後的欄位
*/

#簡單的使用
SELECT SUM(salary) FROM employees;
SELECT AVG(salary) FROM employees;
SELECT MIN(salary) FROM employees;
SELECT MAX(salary) FROM employees;
SELECT COUNT(salary) FROM employees;

SELECT 
  SUM(salary) AS 和,
  AVG(salary) AS 平均,
  MAX(salary) AS 最高,
  MIN(salary) AS 最低,
  COUNT(salary) 個數 
FROM
  employees ;

SELECT 
  SUM(salary) AS 和,
  ROUND(AVG(salary),2) AS 平均,
  MAX(salary) AS 最高,
  MIN(salary) AS 最低,
  COUNT(salary) 個數 
FROM
  employees ;

#和 distinct 搭配
SELECT COUNT(DISTINCT salary) FROM employees; # distinct與引數之間是空格

# count函式的詳細介紹,支援4種過載
SELECT COUNT(salary) FROM employees;
SELECT COUNT(*) FROM employees;  #統計總行數 用的最多
SELECT COUNT(1) FROM employees; #在表中加了 一列 的常量值( 1,2'崔俠'等等常量 ) 並統計行總行數
#效率:
# myisam 儲存引擎下 count(*)的效率最高
# innodb 儲存引擎下 COUNT(*) 和 count(1)的效率差不多, 比 count(欄位)要高一些

#和分組函式一同查詢的欄位有限制
#和分組函式一同查詢的欄位:要求是group by 後的欄位

#查詢公司員工工資的最大值,最小值,平均值,總和
SELECT MAX(salary),MIN(salary),AVG(salary),SUM(salary) FROM employees;

#查詢員工表中的最大入職時間和最小入職時間的長差天數  ( diffrence )
SELECT 
  DATEDIFF(    # datediff函式 計算2個日期之間的天數
    MAX(DISTINCT hiredate),
    MIN(DISTINCT hiredate)
  ) AS 'diffrence' 
FROM
  employees ;

#-------------------------------  
SELECT DATEDIFF(NOW(),'1995.1.1');
  
#查詢部門編號為90的員工個數
SELECT COUNT(*) FROM employees WHERE department_id = 90;
View Code

  5、分組查詢