實用指南:【MYSQL】SQL學習指南:從常見錯誤到高級函數與正則表達式
SQL學習指南:從常見錯誤到高級函數與正則表達式
本文將通過一個具體的SQL報錯案例,帶你逐步深入理解SQL查詢、聚合函數和正則表達式的使用。內容涵蓋錯誤分析、函數詳解和實戰示例,適合SQL初學者和需要查漏補缺的開發者。
文章結構概覽

一、Unknown column ‘sell_date’ in ‘field list’ 錯誤解析
錯誤含義
這個報錯直譯為:“字段列表中找不到名為’sell_date’的列”。意思是SQL語句中引用了一個不存在的列名。
常見原因分析
| 原因 | 說明 | 示例 |
|---|---|---|
| 拼寫錯誤 | 列名拼寫不正確 | 寫成了sel1_date(數字1代替字母l) |
| 大小寫問題 | 數據庫區分大小寫 | 表中是sellDate卻寫了sell_date |
| 字段位置錯誤 | 把列名放在了錯誤的位置 | 在count()中放入了分組列 |
實際問題案例
看這個有問題的SQL:
select distinct(self_date), count(self_date), product Activities
這個SQL存在多個問題:
count(self_date), product Activities是非法語法self_date可能是sell_date的拼寫錯誤product Activities部分語法完全錯誤
正確寫法
假設你想統計每天賣了多少種不同的產品:
SELECT sell_date, COUNT(DISTINCT product) AS product_count
FROM Activities
GROUP BY sell_date
ORDER BY sell_date;
實用建議
在寫SQL前,先用以下命令查看表結構:
DESCRIBE Activities;
-- 或
SHOW COLUMNS FROM Activities;
二、GROUP_CONCAT函數詳解
什么是GROUP_CONCAT?
GROUP_CONCAT是MySQL的專屬聚合函數,作用是將分組后的多行數據中的某個字段值拼接成一個字符串,類似于Excel中的TEXTJOIN或Python中的",".join(list)。
完整語法
GROUP_CONCAT(
[DISTINCT] 列名
[ORDER BY 排序列 ASC|DESC]
[SEPARATOR '分隔符']
)
使用示例
示例數據表t
| id | val |
|---|---|
| 1 | A |
| 1 | B |
| 1 | A |
| 2 | C |
1. 簡單拼接
SELECT id, GROUP_CONCAT(val) AS vals
FROM t
GROUP BY id;
結果:
| id | vals |
|---|---|
| 1 | A,B,A |
| 2 | C |
2. 去重 + 排序 + 自定義分隔符
SELECT id,
GROUP_CONCAT(DISTINCT val
ORDER BY val DESC
SEPARATOR ' | ') AS vals
FROM t
GROUP BY id;
結果:
| id | vals |
|---|---|
| 1 | B |
| 2 | C |
注意事項
| 要點 | 說明 |
|---|---|
| 默認長度限制 | 默認拼接結果最長1024字符,超長會被截斷 |
| 修改長度限制 | SET SESSION group_concat_max_len = 1000000; |
| 跨數據庫兼容 | SQL Server用STRING_AGG,PostgreSQL用STRING_AGG,Oracle用LISTAGG |
實戰應用:銷售數據分組統計
題目要求
- 表:Activities
- 字段:sell_date(日期),product(產品名)
- 需求:按日期分組,統計每天銷售的不同產品數量和產品名稱列表
解決方案
SELECT
sell_date,
COUNT(DISTINCT product) AS num_sold,
GROUP_CONCAT(DISTINCT product ORDER BY product SEPARATOR ',') AS products
FROM Activities
GROUP BY sell_date
ORDER BY sell_date;
輸出示例
| sell_date | num_sold | products |
|---|---|---|
| 2020-05-30 | 2 | Basketball,Headphone |
| 2020-06-01 | 2 | Bible,Pencil |
| 2020-06-02 | 1 | Mask |
三、COUNT(DISTINCT) 函數深度解析
COUNT()的三種常見用法
| 寫法 | 作用 | 是否忽略NULL |
|---|---|---|
| COUNT(*) | 統計所有行數 | 不忽略NULL |
| COUNT(列名) | 統計該列非NULL的行數 | 忽略NULL |
| COUNT(DISTINCT 列名) | 統計該列去重后非NULL值的個數 | 忽略NULL |
為什么用COUNT(DISTINCT product)而不是COUNT(sell_date)?
需求分析
| 要統計什么 | 用什么列 | 原因 |
|---|---|---|
| 每天 | 按sell_date分組 | 分組依據 |
| 賣了多少種不同的產品 | COUNT(DISTINCT product) | 需要統計產品種類數 |
示例數據
| sell_date | product |
|---|---|
| 2020-06-01 | Apple |
| 2020-06-01 | Apple |
| 2020-06-01 | NULL |
| 2020-06-01 | Banana |
查詢與結果
SELECT COUNT(DISTINCT product) AS num_sold
FROM Activities
WHERE sell_date = '2020-06-01';
結果: 2
- Apple重復,只算1次
- NULL被忽略
- 所以結果是2(Apple和Banana)
COUNT(*) vs COUNT(DISTINCT product)
數據示例
| sell_date | product |
|---|---|
| 2020-06-01 | Apple |
| 2020-06-01 | Apple |
| 2020-06-01 | Banana |
對比結果
| SQL | 結果 | 含義 |
|---|---|---|
SELECT COUNT(*) FROM Activities WHERE sell_date = '2020-06-01' | 3 | 這一天有3條銷售記錄 |
SELECT COUNT(DISTINCT product) FROM Activities WHERE sell_date = '2020-06-01' | 2 | 這一天賣過2種產品 |
四、正則表達式REGEXP_LIKE詳解
函數語法
REGEXP_LIKE(被匹配字符串, 正則模式 [, 匹配模式])
參數說明
| 參數 | 含義 | 示例 |
|---|---|---|
| 第1個 | 要匹配的列或字符串 | |
| 第2個 | 正則表達式 | ‘1[a-zA-Z0-9._-]*@leetcode\.com$’ |
| 第3個 | 可選標志位 | ‘c’(區分大小寫)、‘i’(忽略大小寫) |
實際案例解析
REGEXP_LIKE(mail, '^[a-zA-Z][a-zA-Z0-9._-]*@leetcode\\.com$', 'c')
正則模式分解
| 片段 | 含義 |
|---|---|
^ | 字符串開始 |
[a-zA-Z] | 第一個字符必須是字母 |
[a-zA-Z0-9._-]* | 后面跟任意個字母、數字、點、下劃線、短橫 |
@leetcode\\.com | 字面量@leetcode.com |
$ | 字符串結束 |
'c' | 區分大小寫匹配 |
匹配示例
| 郵箱 | 結果 | 原因 |
|---|---|---|
| user_123@leetcode.com | ? | 合法 |
| User@leetcode.com | ? | 合法 |
| 123user@leetcode.com | ? | 首字符不是字母 |
| user@leetcode.com | ? | 大小寫敏感,.Com ≠ .com |
| user@leetcode.com.cn | ? | 后綴多余 |
正則表達式基礎知識
常用元字符
| 符號 | 說明 | 記憶技巧 |
|---|---|---|
. | 任意單字符(換行除外) | dot = "點"通配 |
^ | 行首 | 小箭頭朝上 |
$ | 行尾 | 小箭頭朝下 |
\d | 數字[0-9] | digit |
\D | 非數字[^0-9] | 大寫 = 反義 |
\s | 空白字符[\t\n\r] | space |
\S | 非空白 | 大寫 = 反義 |
\w | 單詞字符[A-Za-z0-9_] | word |
量詞說明
| 符號 | 說明 | 示例 |
|---|---|---|
* | 0次或多次 | a*匹配"", “a”, “aa” |
+ | 1次或多次 | a+匹配"a", “aa” |
? | 0次或1次 | a?匹配"", “a” |
{n} | 恰好n次 | a{3}匹配"aaa" |
{n,} | 至少n次 | a{2,}匹配"aa", “aaa” |
為什么用雙反斜杠"\."?
轉義機制解釋
在SQL字符串中使用正則表達式時需要經過兩層轉義:
| 你寫的 | SQL解析后 | 正則引擎看到 | 含義 |
|---|---|---|---|
'@leetcode\\.com' | @leetcode\.com | @leetcode.com | 字面量點 |
'@leetcode.com' | @leetcode.com | @leetcode.com | 任意字符 |
如果只用單反斜杠\.,SQL會把它當成未知轉義序列,直接扔掉反斜杠,導致正則引擎看到的是普通點號,匹配任意字符。
結論: 在MySQL字符串中,要給正則表達式傳遞字面量點號,必須寫成\\.。
常用正則模板
| 場景 | 正則模式 | 說明 |
|---|---|---|
| 手機號校驗 | ^1[3-9]\d{9}$ | 中國大陸11位手機號 |
| 提取數字 | -?\d+ | 提取第一個整數(支持負數) |
| 壓縮空白 | \s+ | 將連續空白壓縮成單個空格 |
| 郵箱校驗 | ^[a-zA-Z][\w.-]*@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ | 通用郵箱格式 |
五、總結
通過本文的學習,我們掌握了:
- SQL錯誤調試:學會分析"Unknown column"類錯誤,掌握查看表結構的方法
- 高級聚合函數:
- GROUP_CONCAT:字符串拼接利器,支持去重、排序和自定義分隔符
- COUNT(DISTINCT):精確統計唯一值數量
- 正則表達式:
- REGEXP_LIKE函數的使用方法和參數含義
- 常用正則元字符和量詞
- SQL中的轉義機制
記住,SQL學習是一個循序漸進的過程。遇到錯誤不要慌張,學會查閱文檔、理解錯誤信息,并多用示例數據進行測試驗證。希望這篇文章能幫助你在SQL學習的道路上走得更穩更遠!
本文基于實際SQL問題和解決方案整理而成,適用于MySQL數據庫。不同數據庫系統可能有所差異,請根據實際環境調整。
a-zA-Z ??

浙公網安備 33010602011771號