一文分享10個常用的MySQL高級用法
MySQL 有很多高級但實(shí)用的功能,能讓你的查詢變得更簡潔、更高效。
今天分享 10 個我在工作中經(jīng)常使用的 SQL 技巧,不用死記硬背,掌握了就能立刻提升你的數(shù)據(jù)庫操作水平!
1. CTE(WITH子句)——讓復(fù)雜查詢變清晰
-- 傳統(tǒng)子查詢,難以閱讀
SELECT nickname
FROM system_users
WHERE dept_id IN (
SELECT id FROM system_dept WHERE `name` = 'IT部'
);
-- 使用CTE,邏輯清晰
WITH ny_depts AS (
SELECT id FROM system_dept WHERE `name` = 'IT部'
)
SELECT u.nickname
FROM system_users u
JOIN ny_depts nd ON u.dept_id = nd.id;
解釋:
WITH ny_depts AS (...):先創(chuàng)建一個臨時結(jié)果集,叫ny_depts,里面只包含“IT部”的部門名稱。SELECT u.nickname FROM system_users u JOIN ny_depts...:再從用戶表中找出那些部門ID在ny_depts里的員工昵稱。
好處:把找部門和找人分成兩步,邏輯更清楚,比嵌套子查詢好讀多了。
2. 窗口函數(shù) —— 不分組也能統(tǒng)計
SELECT
name,
department,
salary,
RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS rank_in_dept,
AVG(salary) OVER (PARTITION BY department) AS avg_salary
FROM employees;
解釋:
PARTITION BY department:按部門“分組”,但不合并行,每行仍然保留。RANK() OVER (...):在每個部門內(nèi)部,按薪水從高到低排名(相同薪水并列)。AVG(salary) OVER (...):計算每個部門的平均工資,并顯示在每一行里。
對比 GROUP BY:GROUP BY 會把多行合并成一行,而窗口函數(shù)保留原始行,同時加上統(tǒng)計值。
3. 條件聚合 —— 一行查出多個統(tǒng)計
SELECT
YEAR(created_at) AS year,
COUNT(*) AS total,
COUNT(CASE WHEN status = 'completed' THEN 1 END) AS completed,
SUM(CASE WHEN status = 'completed' THEN amount ELSE 0 END) AS revenue
FROM orders
GROUP BY YEAR(created_at);
解釋:
YEAR(created_at):提取訂單年份。COUNT(*):該年總訂單數(shù)。COUNT(CASE WHEN status = 'completed' THEN 1 END): 如果狀態(tài)是'completed',就返回1,否則返回NULL;COUNT()只統(tǒng)計非NULL值,所以這行就是“完成的訂單數(shù)”。SUM(CASE WHEN ... THEN amount ELSE 0 END):只對完成的訂單求金額總和。
關(guān)鍵:不用寫多個子查詢,一條語句搞定全年報表!
4. 自連接 —— 同一張表自己連自己
SELECT e1.name, e2.name FROM employees e1 JOIN employees e2 ON e1.department = e2.department AND e1.id < e2.id AND ABS(e1.salary - e2.salary) <= e1.salary * 0.1;
解釋:
employees e1 JOIN employees e2:把員工表當(dāng)成兩個副本(e1 和 e2)來連接。e1.department = e2.department:只找同一個部門的人。e1.id < e2.id:避免重復(fù)配對(比如 Alice-Bob 和 Bob-Alice 只保留一個)。ABS(...):計算兩人薪水差是否 ≤ 10%。
用途:找“相似記錄”“配對關(guān)系”“上下級”等場景非常有用。
5.EXISTS替代IN—— 更高效的存在判斷
SELECT name FROM customers c
WHERE EXISTS (
SELECT 1 FROM orders o
WHERE o.customer_id = c.id AND o.amount > 1000
);
解釋:
- 對每一位客戶
c,檢查是否存在一筆訂單滿足:- 訂單的
customer_id等于這個客戶的id - 訂單金額 > 1000
- 訂單的
SELECT 1:這里不需要返回具體字段,只要知道“有沒有”就行,所以用1最輕量。- 為什么快?:一旦找到一條匹配訂單,就立刻停止搜索,不像
IN可能要加載全部訂單 ID。
注意:如果子查詢可能返回 NULL,IN 會失效(因?yàn)?x IN (..., NULL) 永遠(yuǎn)為 UNKNOWN),而 EXISTS 不受影響。
6. JSON 函數(shù) —— 輕松讀取 JSON 字段
SELECT
name,
profile->>'$.address.city' AS city,
JSON_EXTRACT(profile, '$.age') AS age
FROM users
WHERE profile->>'$.city' = 'Beijing';
解釋:
profile是一個 JSON 類型字段,比如:{"address": {"city": "Beijing"}, "age": 30}profile->>'$.address.city':->>是簡寫,等價于JSON_UNQUOTE(JSON_EXTRACT(...))- 返回字符串
"Beijing"(去掉引號)
JSON_EXTRACT(profile, '$.age'):返回30(帶類型,可能是數(shù)字)WHERE profile->>'$.city' = 'Beijing':篩選城市是北京的用戶。
適用場景:用戶偏好、動態(tài)表單、日志等結(jié)構(gòu)不固定的字段。
7. 生成列 —— 數(shù)據(jù)庫自動幫你算
CREATE TABLE products (
id INT PRIMARY KEY,
width DECIMAL(10,2),
height DECIMAL(10,2),
area DECIMAL(10,2) AS (width * height) STORED
);
INSERT INTO products (id, width, height) VALUES (1, 5, 10);
解釋:
area DECIMAL(...) AS (width * height) STORED:- 這是一個“存儲型生成列”,數(shù)據(jù)庫會自動計算
width * height并存下來。 - 如果不加
STORED,就是“虛擬列”(每次查詢時計算,不占存儲)。
- 這是一個“存儲型生成列”,數(shù)據(jù)庫會自動計算
- 插入時只需給
width和height,area自動變成50。
優(yōu)勢:避免應(yīng)用層重復(fù)計算,還能給 area 加索引加速查詢!
8. 多表更新 —— 一條語句更新關(guān)聯(lián)數(shù)據(jù)
UPDATE customers c
JOIN (
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
) o ON c.id = o.customer_id
SET c.total_spent = o.total;
解釋:
- 子查詢
o:先按客戶 ID 統(tǒng)計每個人的總消費(fèi)。 UPDATE customers c JOIN o ...:把客戶表和統(tǒng)計結(jié)果連接起來。SET c.total_spent = o.total:直接把統(tǒng)計值寫回客戶表。
好處:不用在程序里循環(huán)“查一個、改一個”,減少網(wǎng)絡(luò)開銷,保證原子性。
9.GROUP_CONCAT—— 多行變一行
SELECT
department,
GROUP_CONCAT(name ORDER BY salary DESC SEPARATOR ', ') AS members
FROM employees
GROUP BY department;
解釋:
GROUP BY department:按部門分組。GROUP_CONCAT(name ...):把每個部門的所有員工名字拼成一個字符串。ORDER BY salary DESC:按薪水從高到低排序后再拼接。SEPARATOR ', ':用逗號加空格分隔名字。
典型用途:導(dǎo)出名單、展示標(biāo)簽、匯總明細(xì)等。
默認(rèn)最多拼 1024 字符,可通過 SET SESSION group_concat_max_len = 1000000; 調(diào)大。
10.INSERT ... ON DUPLICATE KEY UPDATE—— 智能插入/更新
INSERT INTO page_views (page_url, view_date, view_count)
VALUES ('/home', CURDATE(), 1)
ON DUPLICATE KEY UPDATE
view_count = view_count + 1;
解釋:
- 嘗試插入一條新記錄:頁面
/home,今天日期,訪問次數(shù)為 1。 - 如果因?yàn)?strong>唯一索引沖突(比如
(page_url, view_date)是唯一鍵)導(dǎo)致插入失?。?ul> - 就執(zhí)行
ON DUPLICATE KEY UPDATE部分 - 把原有的
view_count加 1
前提:表必須有主鍵或唯一索引,否則不會觸發(fā)更新。
到此這篇關(guān)于一文分享10個常用的MySQL高級用法的文章就介紹到這了,更多相關(guān)MySQL高級用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql5.5 master-slave(Replication)主從配置
在主機(jī)master中對test數(shù)據(jù)庫進(jìn)行sql操作,再查看從機(jī)test數(shù)據(jù)庫是否產(chǎn)生同步。2011-07-07
MySQL數(shù)據(jù)庫定時備份的幾種實(shí)現(xiàn)方法
本文主要介紹了MySQL數(shù)據(jù)庫定時備份的幾種實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07
MySQL計劃任務(wù)(事件調(diào)度器) Event Scheduler介紹
MySQL5.1.x版本中引入了一項(xiàng)新特性EVENT,顧名思義就是事件、定時任務(wù)機(jī)制,在指定的時間單元內(nèi)執(zhí)行特定的任務(wù),因此今后一些對數(shù)據(jù)定時性操作不再依賴外部程序,而直接使用數(shù)據(jù)庫本身提供的功能2013-10-10
MySQL分表自動化創(chuàng)建的實(shí)現(xiàn)方案
在數(shù)據(jù)庫應(yīng)用場景中,隨著數(shù)據(jù)量的不斷增長,單表存儲數(shù)據(jù)可能會面臨性能瓶頸,例如查詢、插入、更新等操作的效率會逐漸降低,分表是一種有效的優(yōu)化策略,它將數(shù)據(jù)分散存儲在多個表中,從而提高數(shù)據(jù)庫的性能和可維護(hù)性,本文介紹了MySQL分表自動化創(chuàng)建的實(shí)現(xiàn)方案2025-01-01
mysql數(shù)據(jù)庫自動添加創(chuàng)建時間及更新時間
在實(shí)際應(yīng)用中我們時常會需要用到創(chuàng)建時間和更新時間這兩個字段,下面這篇文章主要給大家介紹了關(guān)于mysql數(shù)據(jù)庫自動添加創(chuàng)建時間及更新時間的相關(guān)資料,需要的朋友可以參考下2022-05-05
徹底搞懂?dāng)?shù)據(jù)庫操作truncate delete drop關(guān)鍵詞的區(qū)別
這篇文章主要為大家介紹了數(shù)據(jù)庫操作truncate delete drop關(guān)鍵詞的區(qū)別,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09
centos7下mysqldump定時備份數(shù)據(jù)庫的方法實(shí)現(xiàn)
MySQL Dump是MySQL提供的方便導(dǎo)出數(shù)據(jù)庫數(shù)據(jù)的工具,本文主要介紹了centos7下mysqldump定時備份數(shù)據(jù)庫的方法實(shí)現(xiàn),感興趣的可以了解一下2023-08-08

