【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:

sql 复制代码
select distinct(self_date), count(self_date), product Activities

这个SQL存在多个问题:

  • count(self_date), product Activities 是非法语法
  • self_date 可能是 sell_date 的拼写错误
  • product Activities 部分语法完全错误

正确写法

假设你想统计每天卖了多少种不同的产品:

sql 复制代码
SELECT sell_date, COUNT(DISTINCT product) AS product_count
FROM Activities
GROUP BY sell_date
ORDER BY sell_date;

实用建议

在写SQL前,先用以下命令查看表结构:

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. 简单拼接
sql 复制代码
SELECT id, GROUP_CONCAT(val) AS vals
FROM t
GROUP BY id;

结果:

id vals
1 A,B,A
2 C
2. 去重 + 排序 + 自定义分隔符
sql 复制代码
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(产品名)
  • 需求:按日期分组,统计每天销售的不同产品数量和产品名称列表
解决方案
sql 复制代码
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
查询与结果
sql 复制代码
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个 要匹配的列或字符串 mail
第2个 正则表达式 '^[1](#参数 含义 示例 第1个 要匹配的列或字符串 mail 第2个 正则表达式 ‘1[a-zA-Z0-9._-]*@leetcode.com’ 第3个 可选标志位 ‘c’(区分大小写)、‘i’(忽略大小写))^\[a-zA-Z0-9._-\]\*@leetcode\\.com'
第3个 可选标志位 'c'(区分大小写)、'i'(忽略大小写)

实际案例解析

sql 复制代码
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,}$ 通用邮箱格式

五、总结

通过本文的学习,我们掌握了:

  1. SQL错误调试:学会分析"Unknown column"类错误,掌握查看表结构的方法
  2. 高级聚合函数
    • GROUP_CONCAT:字符串拼接利器,支持去重、排序和自定义分隔符
    • COUNT(DISTINCT):精确统计唯一值数量
  3. 正则表达式
    • REGEXP_LIKE函数的使用方法和参数含义
    • 常用正则元字符和量词
    • SQL中的转义机制

记住,SQL学习是一个循序渐进的过程。遇到错误不要慌张,学会查阅文档、理解错误信息,并多用示例数据进行测试验证。希望这篇文章能帮助你在SQL学习的道路上走得更稳更远!


本文基于实际SQL问题和解决方案整理而成,适用于MySQL数据库。不同数据库系统可能有所差异,请根据实际环境调整。


  1. a-zA-Z ↩︎
相关推荐
叫我龙翔5 小时前
【MySQL】从零开始了解数据库开发 --- 数据表的约束
android·c++·mysql·数据库开发
流烟默6 小时前
MySQL索引调优之索引顺序必须和字段顺序一致吗?
mysql·索引调优
十碗饭吃不饱7 小时前
sql报错:java.sql.SQLSyntaxErrorException: Unknown column ‘as0‘ in ‘where clause‘
java·数据库·sql
我是Superman丶7 小时前
【优化】Mysql指定索引查询或忽略某个索引
数据库·mysql
呆呆小金人7 小时前
SQL入门: HAVING用法全解析
大数据·数据库·数据仓库·sql·数据库开发·etl·etl工程师
LL_break8 小时前
Mysql数据库
java·数据库·mysql
星光一影11 小时前
【OA办公系统】神点企业OA办公助手/全开源
mysql·nginx·开源·php·源代码管理
华仔啊12 小时前
千万级大表如何新增字段?别再直接 ALTER 了
后端·mysql