分組查詢
分組查詢(Group By)是在關系型數據庫中用來對數據進行分組并對每個組應用聚合函數的一種操作。這種查詢通常結合聚合函數(如 COUNT、SUM、AVG、MAX、MIN 等)使用,用于在查詢結果中生成匯總信息
特點(聚合):輸入多行,最終輸出一行,且分組函數(COUNT、SUM、AVG、MAX、MIN)需要分組了才能使用,如果不進行分組則將會聚合整張表的數據
語法
SELECT 字段1, 分組/聚合函數(字段2)
FROM 表名
WHERE 條件
GROUP BY 字段1;
分組查詢的工作原理如下:
- 數據庫首先按照
GROUP BY
子句中指定的列對數據進行分組。 - 然后,對每個分組應用
SELECT
中指定的聚合函數,計算每個分組的匯總值。 - 最后,返回每個分組的匯總結果作為查詢結果集。
注意事項
- 必須包含在 SELECT 子句中的列:在使用 GROUP BY 子句時,SELECT 子句中的列要么是分組列,要么是聚合函數。非聚合函數列必須包含在 GROUP BY 子句中,否則將導致語法錯誤。
- NULL 值處理:分組查詢中,數據庫會將 NULL 值視為一個分組。
- 性能考慮:當數據量較大時,分組查詢可能會影響性能,尤其是在沒有正確索引支持的情況下。
聚合/分組函數
COUNT
計算某一列中的行數,或者符合特定條件的行數。
假設有一個 students
表,包含學生的信息,可以使用 COUNT() 函數來統計學生的總數或者符合某些條件的學生數。
-- 統計學生總數
SELECT COUNT(*) AS total_students
FROM students;-- 統計年齡大于等于 18 歲的學生數
SELECT COUNT(*) AS adults
FROM students
WHERE age >= 18;
SUM
計算數值列的總和。
示例: 假設有一個 orders
表,包含訂單信息,可以使用 SUM() 函數來計算訂單總金額。
-- 計算所有訂單的總金額
SELECT SUM(order_amount) AS total_amount
FROM orders;-- 計算特定客戶的訂單總金額
SELECT customer_id, SUM(order_amount) AS total_spent
FROM orders
WHERE customer_id = 123
GROUP BY customer_id;
AVG
計算數值列的平均值。
示例: 繼續使用 orders
表的例子,可以使用 AVG() 函數來計算平均訂單金額。
sql-- 計算所有訂單的平均金額
SELECT AVG(order_amount) AS average_amount
FROM orders;-- 計算特定客戶的平均訂單金額
SELECT customer_id, AVG(order_amount) AS average_spent
FROM orders
WHERE customer_id = 123
GROUP BY customer_id;
MAX
找出數值列的最大值。
示例: 使用 MAX() 函數來查找訂單表order
中的最高訂單金額。
sql-- 找出訂單表中的最高訂單金額
SELECT MAX(order_amount) AS max_amount
FROM orders;-- 找出每個客戶的最高訂單金額
SELECT customer_id, MAX(order_amount) AS max_spent
FROM orders
GROUP BY customer_id;
MIN
找出數值列的最小值。
示例: 使用 MIN() 函數來查找訂單表order
中的最低訂單金額。
-- 找出訂單表中的最低訂單金額
SELECT MIN(order_amount) AS min_amount
FROM orders;-- 找出每個客戶的最低訂單金額
SELECT customer_id, MIN(order_amount) AS min_spent
FROM orders
GROUP BY customer_id;
連接查詢
從一張表中單獨查詢,稱為單表查詢。假設有a表和b表聯合起來查詢數據,從表a中取a1字段,從b表中取b1字段。這種跨表查詢,多張表聯合起來查詢數據,被稱為連接查詢。
連接查詢的應用場景
- 關聯查詢:用于在多個表中檢索相關聯的數據,比如客戶和訂單、產品和訂單等。
- 數據整合:將多個表中的數據整合為一個結果集,便于分析和報告。
- 復雜條件過濾:通過連接不同表,并結合條件過濾,可以實現復雜的數據查詢和分析需求。
- 數據分析和報表:連接查詢可以幫助生成更具體和詳細的報表,涵蓋多個業務方面的數據。
表連接的方式分類
內連接:
- 等值連接
- 非等值連接
- 自連接
外連接:
- 左外連接(左連接)
- 右外連接(右連接)
- 全連接(FULL JOIN)
??注意避免笛卡爾積
當兩張表進行連接查詢的時候,沒有任何條件限制會發生笛卡爾積現象
例如A表有1000條數據,B表有200條數據,同時在鏈接查詢時并沒有去做表的連接限制,例如ON關鍵字(下面會講),或者Where關鍵字,那么查詢出的數據行數約:1000 * 200 = 200000條數據,且很大可能性沒有任何質量
語法
內連接查詢(AB兩個表沒有主次關系)
- 等值連接
SELECT 字段
FROM 表1 INNER JOIN 表2 ON 表1.字段 = 表2.字段
WHERE 條件-- orders 表和 customers 表通過 customer_id 列進行內連接,返回訂單信息和對應客戶的名稱。
SELECT orders.order_id, customers.customer_name
FROM orders
INNER JOIN customers ON orders.customer_id = customers.customer_id;
- 非等值連接
SELECT 字段
FROM 表1 INNER JOIN 表2 ON 表1.字段 between 表2.字段1 and 表2.字段2
WHERE 條件-- 找出員工的薪資等級
SELECT e.name,e.sal,s.grade
FROM emp e INNER JOIN salgrade s
ON e.sal BETWEEN s.losal AND s.hisal
- 自連接
- 自連接就是同一張表進行連接查詢
SELECT 字段
FROM 表1 INNER JOIN 表1 ON 表1.字段1 = 表1.字段2
WHERE 條件
-- 查詢員工的上級領導
SELECT a.ename AS '員工名',b.ename AS '領導名'
FROM
emp a INNER JOIN emp b
a.mgr = b.empno
外連接(AB兩個表有主次關系)
- 左連接(Left Join)
- 左連接返回左邊表(即左表)中的所有行,以及右表中滿足連接條件的行。如果右表中沒有匹配的行,則返回 NULL 值。
-- 語法
SELECT 列名 FROM 表1 LEFT JOIN 表2 ON 表1.列 = 表2.列-- 返回所有客戶的名稱,以及他們的訂單信息(如果有的話),如果客戶沒有訂單,則訂單信息列顯示為 NULL
SELECT customers.customer_name, orders.order_id
FROM customers
LEFT JOIN orders ON customers.customer_id = orders.customer_id;
- 右連接(Right Join)
- 右連接與左連接類似,不同之處在于它返回右表中的所有行,以及左表中滿足連接條件的行。如果左表中沒有匹配的行,則返回 NULL 值。
-- 語法
SELECT 列名 FROM 表1 RIGHT JOIN 表2 ON 表1.列 = 表2.列-- 返回所有訂單的信息,以及對應的客戶名稱,如果訂單沒有對應的客戶信息,則客戶名稱列顯示為 NULL。
SELECT orders.order_id, customers.customer_name
FROM orders
RIGHT JOIN customers ON orders.customer_id = customers.customer_id;
- 全連接(Full Join):
- 全連接返回左表和右表中所有的行,無論是否滿足連接條件。
-- 語法
SELECT 列名 FROM 表1 FULL JOIN 表2 ON 表1.列 = 表2.列-- 返回所有客戶和訂單的組合,無論是否有匹配的條件。
-- 如果某個客戶沒有訂單或某個訂單沒有客戶,則對應的列會顯示 NULL。
SELECT customers.customer_name, orders.order_id
FROM customers
FULL JOIN orders ON customers.customer_id = orders.customer_id;
??注意事項
性能影響:連接操作可能會影響查詢性能,特別是在大型數據集上或者未優化的情況下。
索引優化:在進行連接查詢之前,確保相關的連接字段上存在適當的索引,可以提高查詢效率。
結果集理解:理解不同類型連接查詢的行為和生成的結果集,以避免數據丟失或者意外的數據組合。
子查詢
查詢語句中嵌套的select語句被稱為子查詢
子查詢出現在如下部分:查詢的字段列表中、FROM的臨時表、WHERE的子條件,如下
SELECT 字段..,(子查詢)
FROM ..,(子查詢)
WHERE ..,(子查詢)
現在有一張表為員工薪資表emp
where中的子查詢
- 利用where子查詢找出工資最低的員工信息
SELECT ename,sal
FROM emp
WHERE sal > (SELECT MIN(sal) FROM emp)
from中的子查詢
from后的子查詢,可以將子查詢的結果當做一張臨時表
- 利用from子查詢找出每個崗位的平均工資的薪資等級
SELECT
t.*,s.grade
FROM
(SELECT job,avg(sal) as avgsal FROM emp group by job) t
INNER JOIN
salgrade s
ON t.avgsal BETWEEN s.losal AND s.hisal
select中的子查詢
- 利用select的子查詢實現根據員工編號獲取員工的部門名稱
SELECT
e.ename,e.deptno,(SELECT d.dname FROM dept d WHERE e.deptno = d.deptno) as dname
FROM emp e