MySQL_基礎_DQL數據查詢語言

查詢語法

語法:
    SELECT * | { [DISTINCT] column | expression [alias], ... }
    FROM table
    [[connect_type] JION table2 ON connect_condition]
    [WHERE condition]
    [GROUP BY columns]
    [HAVING condition]
    [ORDER BY columns (ASC | DESC)]
    [LIMIT { [offset,] row_count | row_count OFFSET offset }];

語句順序:
    查詢語句書寫順序:SELECT –> FROM -> JION -> ON -> WHERE -> GROUP BY -> HAVING -> ORDER BY -> LIMIT
    查詢語句執行順序:FROM -> JION -> ON -> WHERE -> GROUP BY -> HAVING -> SELECT –> ORDER BY -> LIMIT

 

基本查詢

語法:
 SELECT * | { [DISTINCT] column | expression [alias], ... } FROM table;

特色:
    1、查詢列表能夠是:表中的字段、常量值、表達式、函數
    2、查詢的結果是一個虛擬的表格

案例:
    1、查詢表中的單個字段
    SELECT last_name FROM employees;

    2、查詢表中的多個字段
    SELECT last_name,salary,email FROM employees;

    3、查詢表中的全部字段  
    SELECT * FROM employees;
     
    4、查詢常量值
    SELECT 100;
    SELECT 'john';
     
    5、查詢表達式
    SELECT 100%98;
     
    6、查詢函數
    SELECT VERSION();
     
    7、起別名,AS
    SELECT last_name AS 姓,first_name AS 名 FROM employees;
    SELECT last_name 姓,first_name 名 FROM employees;

    8、消除重複數據,DISTINCT
    SELECT DISTINCT department_id FROM employees;

    9、+號的做用
    SELECT 100+90;            # 兩個操做數都爲數值型,則作加法運算
    SELECT 'john'+90;         # 一方爲字符型,試圖轉換成數值型,轉換成功則作加法運算,轉換失敗則轉換成0再運算
    SELECT null+10;           # 一方爲null,結果爲null 10、字符串鏈接
    SELECT CONCAT('a','b','c') AS 結果;

 

條件查詢

語法:
    SELECT * | { [DISTINCT] column | expression [alias], ... }
    FROM table
    [WHERE condition];

分類:
    1、條件運算符
        > < = != <> >= <=         # 判斷普通值
        <=>                       # 安全等於,便可以判斷null值,又能夠判斷普通值,與is null比較可讀較低

    2、邏輯運算符
        &&或AND                   # 邏輯並,兩個條件都爲true,結果爲true,反之爲false ||或OR                    # 邏輯或,只要有一個條件爲true,結果爲true,反之爲false !或NOT                    # 邏輯否,若是鏈接的條件自己爲false,結果爲true,反之爲false 3、模糊查詢
        LIKE                      # 模糊查詢,% 任意多個字符,_ 任意單個字符
        BETWEEN AND               # 在兩個值之間(包含邊界)
        IN                        # 等於值列表中的一個
        IS (NOT) NULL             # 判斷null值

案例:
    1、按條件表達式篩選
        案例1:查詢工資>12000的員工信息
        SELECT * FROM employees WHERE salary>12000;
            
        案例2:查詢部門編號不等於90號的員工名和部門編號
        SELECT last_name,department_id FROM employees WHERE department_id<>90;

        案例3:查詢沒有獎金的員工名和獎金率
        SELECT last_name,commission_pct FROM employees WHERE commission_pct <=> NULL;

        案例4:查詢工資爲12000的員工信息
        SELECT last_name,salary FROM employees WHERE salary <=> 12000;

    2、按邏輯表達式篩選
        案例1:查詢工資z在10000到20000之間的員工名、工資以及獎金
        SELECT last_name,salary,commission_pct FROM employees WHERE salary>=10000 AND salary<=20000;

        案例2:查詢部門編號不是在90到110之間,或者工資高於15000的員工信息
        SELECT * FROM employees WHERE NOT(department_id>=90 AND department_id<=110) OR salary>15000;

    3、模糊查詢
        LIKE:
            案例1:查詢員工名中包含字符a的員工信息
            SELECT * FROM employees WHERE last_name LIKE '%a%';

            案例2:查詢員工名中第三個字符爲e,第五個字符爲a的員工名和工資
            SELECT last_name,salary FROM employees WHERE last_name LIKE '__e_a%';

            案例3:查詢員工名中第二個字符爲_的員工名
            SELECT last_name FROM employees WHERE last_name LIKE '_\_%';
            SELECT last_name FROM employees WHERE last_name LIKE '_$_%' ESCAPE '$';

        BETWEEN AND:
            案例1:查詢員工編號在100到120之間的員工信息
            SELECT * FROM employees WHERE employee_id >= 100 AND employee_id<=120;
            SELECT * FROM employees WHERE employee_id BETWEEN 100 AND 120;

        IN:
            案例1:查詢員工的工種編號是 IT_PROG、AD_VP、AD_PRES中的一個員工名和工種編號
            SELECT last_name,job_id FROM employees WHERE job_id = 'IT_PROT' OR job_id = 'AD_VP' OR JOB_ID ='AD_PRES';
            SELECT last_name,job_id FROM employees WHERE job_id IN( 'IT_PROT' ,'AD_VP','AD_PRES');

        IS (NOT) NULL:
            案例1:查詢沒有獎金的員工名和獎金率
            SELECT last_name,commission_pct FROM employees WHERE commission_pct IS NULL;

            案例2:查詢有獎金的員工名和獎金率
            SELECT last_name,commission_pct FROM employees WHERE commission_pct IS NOT NULL;

 

排序查詢

語法:
    SELECT * | { [DISTINCT] column | expression [alias], ... }
    FROM table
    [WHERE condition]
    [ORDER BY columns (ASC | DESC)];

特色:
    1、ASC升序(默認,可省略),DESC降序
    2、ORDER BYy子句能夠支持 單個字段、別名、表達式、函數、多個字段
    3、ORDER BY子句在查詢語句的最後面,除了LIMIT子句

案例:
    1、按單個字段排序
        案例:查詢員工信息,要求先按工資降序
        SELECT * FROM employees ORDER BY salary DESC;

    2、按多個字段排序
        案例:查詢員工信息,要求先按工資降序,再按employee_id升序
        SELECT * FROM employees ORDER BY salary DESC,employee_id ASC;

    3、添加篩選條件再排序
        案例:查詢部門編號>=90的員工信息,並按員工編號降序
        SELECT * FROM employees WHERE department_id>=90 ORDER BY employee_id DESC;

    4、按表達式排序
        案例:查詢員工信息 按年薪降序
        SELECT *,salary*12*(1+IFNULL(commission_pct,0)) FROM employees ORDER BY salary*12*(1+IFNULL(commission_pct,0)) DESC;

    5、按別名排序
        案例:查詢員工信息 按年薪升序
        SELECT *,salary*12*(1+IFNULL(commission_pct,0)) 年薪 FROM employees ORDER BY 年薪 ASC;

    6、按函數排序
        案例:查詢員工名,而且按名字的長度降序
        SELECT LENGTH(last_name),last_name FROM employees ORDER BY LENGTH(last_name) DESC;

 

函數查詢

經常使用函數:
    字符函數:LENGTH、CONCAT、SUBSTR、REPLACE、INSTR、TRIM、LPAD、RPAD、UPPER、LOWER...
    數字函數:ROUND、CEIL、FLOOR、ABS、POWER、TRUNCATE、MOD..
    日期函數:NOW、CURDATE、CURTIME、YEAR、MONTH、DAY、HOUR、MINUTE、SECOND、STR_TO_DATE、DATE_FORMAT..
    流程控制函數:IFNULL、NULLIF、IF、CASE..
    其餘函數:VERSION、DATABASE、USER..
    聚合函數:SUM、AVG、MIN、MAX、COUNT..

案例:
    1、字符函數
        SELECT LENGTH('hello');                         # 取字符串長度,結果:5
        SELECT CONCAT('Hello','world');                 # 鏈接字符串,結果:Helloworld
        SELECT SUBSTR('abcdefg',3,2);                   # 截取字符串,結果:cd
        SELECT REPLACE('jack and jue','j','bl');        # 替換字符串,結果:black and blue
        SELECT INSTR('worldworld','r');                 # 查找子串第一次索引,結果:3
        SELECT TRIM('*' FROM '***hello***world***');    # 去除先後字符串,結果:hello***world
        SELECT LPAD('abc',10,'*');                      # 左填充,結果:*******abc
        SELECT RPAD('abc',10,'*');                      # 右填充,結果:abc*******
        SELECT UPPER('sun');                            # 轉換爲大寫,結果:SUN
        SELECT LOWER('FUN');                            # 轉換爲小寫,結果:fun 2、數學函數:
        SELECT ROUND(100.256,2);                        # 四捨五入,結果:100.26
        SELECT CEIL(44.778);                            # 向上取整,結果:45
        SELECT FLOOR(100.2);                            # 向下取整,結果:100
        SELECT ABS(-15);                                # 取絕對值,結果:15
        SELECT POWER(4,2);                              # m的n次冪,結果:16
        SELECT TRUNCATE(100.256,2);                     # 截斷,結果:100.25
        SELECT MOD(10,3);                               # 取餘數,結果:1
        SELECT RAND();                                  # 0-1之間隨機數,結果:0.341342691650002

    3、日期函數:
        SELECT NOW();                                   # 返回當前系統日期時間
        SELECT CURDATE();                               # 返回當前系統日期
        SELECT CURTIME();                               # 返回當前系統時間
        SELECT YEAR(NOW());                             # 返回當前系統的年
        SELECT MONTH(NOW());                            # 返回當前系統的月
        SELECT DAY(NOW());                              # 返回當前系統的日
        SELECT HOUR(NOW());                             # 返回當前系統的時
        SELECT MINUTE(NOW());                           # 返回當前系統的分
        SELECT SECOND(NOW());                           # 返回當前系統的秒
        SELECT STR_TO_DATE('1980-01-01','%Y-%c-%d');    # 將字符轉換成日期
        SELECT DATE_FORMAT(NOW(),'%y年%m月%d日');        # 將日期轉換成字符
        SELECT DATEDIFF('2020-01-01', NOW());           # 返回兩日期相差天數 4、流程控制函數                        
        SELECT IFNULL(NULL,123);                                              # 若是expr1不是NULL,返回expr1,不然返回expr2
        SELECT NULLIF(1,2);                                                   # 若是expr1=expr2,返回NULL,不然返回expr1
        SELECT IF(1<2,'yes','no');                                            # 若是expr1是真, 返回expr2, 不然返回expr3
        SELECT CASE 1 WHEN 1 THEN 'one' WHEN 2 THEN 'two' ELSE 'more' END;    # 枚舉這個字段全部可能的值
        SELECT CASE WHEN 1>0 THEN 'true' ELSE 'false' END;                    # 判斷字段範圍 5、其餘函數:
        SELECT VERSION();                               # 返回MySql版本
        SELECT DATABASE();                              # 返回當前數據庫
        SELECT USER();                                  # 返回當前用戶
        SELECT PASSWORD('123456');                      # 返回該字符的密碼形式
        SELECT MD5('123456');                           # 返回該字符的MD5加密形式
        SELECT UUID();                                  # 返回UUID 6、聚合函數
        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 [column,] group function(column), ...
    FROM table
    [WHERE condition]
 [GROUP BY columns] [HAVING condition]
    [ORDER BY columns (ASC | DESC)];

案例:
    1、簡單分組
        案例:查詢每一個工種的員工平均工資
        SELECT AVG(salary),job_id FROM employees GROUP BY job_id;

    2、分組前篩選
        案例:查詢郵箱中包含a字符的 每一個部門的最高工資
        SELECT MAX(salary),department_id FROM employees WHERE email LIKE '%a%' GROUP BY department_id;

    3、分組後篩選
        案例:查詢哪一個部門的員工個數>5
        SELECT COUNT(*),department_id FROM employees GROUP BY department_id HAVING COUNT(*)>5;

    4、多個字段分組
        案例:查詢每一個工種每一個部門的最低工資,並按最低工資降序
        SELECT MIN(salary),job_id,department_id FROM employees GROUP BY department_id,job_id ORDER BY MIN(salary) DESC;

 

分頁查詢

語法:
    SELECT * | { [DISTINCT] column | expression [alias], ... }
    FROM table
    [WHERE condition]
    [GROUP BY columns]
    [HAVING condition]
    [ORDER BY columns (ASC | DESC)]
    [LIMIT { [offset,] row_count | row_count OFFSET offset }];

注意:
    offset表明起始索引,默認0

案例:
    1、查詢前五條員工信息
    SELECT * FROM  employees LIMIT 0,5;
    SELECT * FROM  employees LIMIT 5;

    2、查詢第11條——第25條
    SELECT * FROM  employees LIMIT 10,15;
    SELECT * FROM  employees LIMIT 15 OFFSET 10;

 

鏈接查詢

語法:
    SELECT * | { [DISTINCT] column | expression [alias], ... }
    FROM table
    [[connect_type] JION table2 ON connect_condition]
    [WHERE condition]
    [GROUP BY columns]
    [HAVING condition]
    [ORDER BY columns (ASC | DESC)]
    [LIMIT { [offset,] row_count | row_count OFFSET offset }];

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

笛卡爾乘積現象:
    表1 有m行,表2 有n行,結果=m*n行

    發生緣由:沒有有效的鏈接條件
    如何避免:添加有效的鏈接條件

分類:
    按年代分類:
        sql92標準:僅僅支持內鏈接
        sql99標準:支持內鏈接+外鏈接(左外和右外)+交叉鏈接
    
    按功能分類:
        內鏈接:[INNER] JOIN ON 
            等值鏈接
            非等值鏈接
            自鏈接
        外鏈接:
            左外鏈接:LEFT [OUTER] JOIN
            右外鏈接:RIGHT [OUTER] JOIN
            全外鏈接:FULL [OUTER] JOIN(MySQL不支持)
        交叉鏈接:CROSS JOIN(笛卡爾集)

說明:
    內鏈接:
        特色:
            1、內鏈接結果 = 多表的交集部分
            2、n錶鏈接至少須要n-1個鏈接條件
            3、多表的順序沒有要求
            4、inner能夠省略
            5、篩選條件放在where後面,鏈接條件放在on後面,提升分離性,便於閱讀
            6、inner join鏈接和sql92語法中的等值鏈接效果是同樣的,都是查詢多表的交集
        
    外鏈接:
        特色:
            1、外鏈接結果 = 內鏈接結果+主表中有而從表沒有的記錄
            2、left join左邊的是主表,right join右邊的是主表,full join兩邊都是主表
            3、左外和右外交換兩個表的順序,能夠實現一樣的效果 
            4、通常用於查詢除了交集部分的剩餘的不匹配的行
            5、全外鏈接結果 = 內鏈接的結果+表1中有但表2沒有的+表2中有但表1沒有的

案例:
    內鏈接:
        1、等值鏈接
            案例1.查詢員工名、部門名
            SQL92語法:SELECT last_name,department_name FROM departments d,employees e WHERE e.`department_id`=d.`department_id`;
            SQL99語法:SELECT last_name,department_name FROM departments d JOIN  employees e ON e.`department_id`=d.`department_id`;

            案例2:查詢員工名、部門名和所在的城市
            SQL92語法:SELECT last_name,department_name,city FROM employees e,departments d,locations l 
                        WHERE e.`department_id`=d.`department_id` AND d.`location_id`=l.`location_id`;
            SQL99語法:SELECT last_name,department_name,city FROM employees e 
                        INNER JOIN departments d ON e.`department_id`=d.`department_id`
                        INNER JOIN locations l ON d.`location_id`=l.`location_id`;

        2、非等值鏈接
            案例:查詢員工的工資和工資級別
            SQL92語法:SELECT salary,grade_level FROM employees e,job_grades g WHERE e.`salary` BETWEEN g.`lowest_sal` 
AND g.`highest_sal`; SQL99語法:SELECT salary,grade_level FROM employees e JOIN job_grades g ON e.`salary` BETWEEN g.`lowest_sal`
AND g.`highest_sal`;
3、自鏈接 案例:查詢員工名和上級的名稱 SQL92語法:SELECT e.last_name,m.last_name FROM employees e,employees m WHERE e.`manager_id`=m.`employee_id`; SQL99語法:SELECT e.last_name,m.last_name FROM employees e JOIN employees m ON e.`manager_id`=m.`employee_id`; 外鏈接: 1、左、右外鏈接 案例:查詢哪一個部門沒有員工 左外鏈接:SELECT d.*, e.employee_id FROM departments d LEFT OUTER JOIN employees e ON d.`department_id`=e.`department_id` WHERE e.`employee_id` IS NULL; 右外鏈接:SELECT d.*, e.employee_id FROM employees e RIGHT OUTER JOIN departments d ON d.`department_id`=e.`department_id` WHERE e.`employee_id` IS NULL; 2、交叉鏈接(笛卡爾集) 案例:查詢兩表數據 笛卡爾集:SELECT d.*,e.* FROM departments d,employees e; 交叉鏈接:SELECT d.*,e.* FROM departments d CROSS JOIN employees e;

 

子查詢

含義:
    嵌套在其餘語句內部的select語句稱爲子查詢或內查詢
    外部語句能夠是insert、update、dalete、select等,通常select做爲外部語句較多
    外部若是爲select語句稱爲主查詢或外查詢

分類:
    按子查詢出現的位置:
        SELECT後面:支持標量子查詢
        FROM後面:支持表子查詢
        WHERE或HAVING後面:支持標量子查詢、列子查詢、行子查詢
        EXISTS後面:支持標量子查詢、列子查詢、行子查詢、表子查詢
            
    按結果集的行列數不一樣:
        標量子查詢(結果集只有一行一列)
        列子查詢(結果集只有一列多行)
        行子查詢(結果集有一行多列)
        表子查詢(結果集通常爲多行多列)

特色:
    1、子查詢放在小括號內
    2、子查詢通常放在條件的右側
    3、標量子查詢,通常搭配着單行操做符使用> < >= <= = <>
    4、列子查詢,通常搭配着多行操做符使用 (NOT) IN、ANY|SOME、ALL
        (NOT) IN:等於列表中的任意一個
        ANY|SOME:和子查詢返回的某一個值比較
        ALL:和子查詢返回的全部值比較
    5、子查詢的執行優先於主查詢執行,主查詢的條件用到了子查詢的結果

案例:
    1、標量子查詢
        案例1:查詢公司工資最少的員工的last_name,job_id和salary
        SELECT last_name,job_id,salary FROM employees WHERE salary=(
            SELECT MIN(salary) FROM employees
        );
        
        案例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
        );

    2、列子查詢
        案例1:查詢location_id是1400或1700的部門中的全部員工姓名
        SELECT last_name FROM employees WHERE department_id IN(
            SELECT DISTINCT department_id FROM departments WHERE location_id IN(1400,1700)
        );
        # 或
        SELECT last_name FROM employees WHERE department_id =ANY(
            SELECT DISTINCT department_id FROM departments WHERE location_id IN(1400,1700)
        );
        
        案例2:查詢location_id不是1400或1700的部門中的全部員工姓名
        SELECT last_name FROM employees WHERE department_id NOT IN(
            SELECT DISTINCT department_id FROM departments WHERE location_id IN(1400,1700)
        );
        # 或
        SELECT last_name FROM employees WHERE department_id <>ALL(
            SELECT DISTINCT department_id FROM departments WHERE location_id IN(1400,1700)
        );

        案例3:查詢其它工種中比job_id爲‘IT_PROG’工種任一工資低的員工的員工號、姓名、job_id 以及salary
        SELECT last_name,employee_id,job_id,salary FROM employees WHERE salary<ANY(
            SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG'
        ) AND job_id<>'IT_PROG';
        # 或
        SELECT last_name,employee_id,job_id,salary FROM employees WHERE salary<(
            SELECT MAX(salary) FROM employees WHERE job_id = 'IT_PROG'
        ) AND job_id<>'IT_PROG';

        案例4:查詢其它工種中比job_id爲‘IT_PROG’工種全部工資低的員工的員工號、姓名、job_id 以及salary
        SELECT last_name,employee_id,job_id,salary FROM employees WHERE salary<ALL(
            SELECT DISTINCT salary FROM employees WHERE job_id = 'IT_PROG'
        ) AND job_id<>'IT_PROG';
        # 或
        SELECT last_name,employee_id,job_id,salary FROM employees WHERE salary<(
            SELECT MIN(salary) FROM employees WHERE job_id = 'IT_PROG'
        ) AND job_id<>'IT_PROG';

    3、行子查詢
        案例:查詢員工編號最小而且工資最高的員工信息
        SELECT * FROM employees WHERE employee_id=(
            SELECT MIN(employee_id) FROM employees
        )AND salary=(
            SELECT MAX(salary) FROM employees);
        # 或
        SELECT * FROM employees WHERE (employee_id,salary)=(
            SELECT MIN(employee_id),MAX(salary) FROM employees
        );
    
    4、表子查詢
        案例:查詢有員工的部門名
        SELECT department_name FROM departments d WHERE EXISTS(
            SELECT * FROM employees e WHERE d.`department_id`=e.`department_id`
        );

 

聯合查詢

語法:
    SELECT1 ...
    UNION [ALL | DISTINCT]
    SELECT2 ...
    ...

應用場景:
    要查詢的結果來自於多個表,且多個表沒有直接的鏈接關係,但查詢的信息一致時

特色:
    1、要求多條查詢語句的查詢列數是一致的!
    2、要求多條查詢語句的查詢的每一列的類型和順序最好一致
    3、union關鍵字默認去重,若是使用union all 能夠包含重複項
    4、多個select語句聯合查詢後的結果字段,都是以第一個select語句的字段爲準

案例:
    1、查詢部門編號>90或郵箱包含a的員工信息
    SELECT * FROM employees WHERE email LIKE '%a%' OR department_id>90;

    # 或
    SELECT * FROM employees  WHERE email LIKE '%a%'
    UNION
    SELECT * FROM employees  WHERE department_id>90;
相關文章
相關標籤/搜索