SQL_单表查询

SQL中的DQL详解

本篇内容系统性地讲解了 SQL 中 DQL(Data Query Language,数据查询语言)的核心语法与使用技巧,帮助你掌握单表查询的完整流程与应用。

1. 基本查询

 我们先从最基本的SELECT和FROM的组合开始学习

查询表的全部字段 (*代表选择所有的字段):

SELECT * 
FROM 表名;    

e.g. 查询user表中全部字段
SELECT * 
FROM users; 

限定字段,仅查询该表的某些字段:

SELECT 字段1, 字段2, …… 
FROM 表名;

e.g. 查询user表中的 id 和 name 字段
SELECT id, name 
FROM users

2. WHERE 查询限制条件

 接下来,我们增加WHERE来限制我们要查询的条件。

 既然WHERE之后紧跟的是我们的限制条件,那我们从限制入手,来学习在WHERE中我们可以增加哪些限制:

(1) 比较操作符

操作符含义示例
=等于WHERE age = 25
<>不等于WHERE status <> 'active'
>大于WHERE salary > 5000
<小于WHERE age < 30
>=大于等于WHERE score >= 60
<=小于等于WHERE age <= 50
SELECT 字段1, 字段2, …… 
FROM 表名 
WHERE 字段 比较运算符 值;
e.g.
-- 查询 状态不是 active 的用户,比如“冻结”、“注销”。
SELECT id, name 
FROM users 
WHERE status <> 'active';

(2) 范围限制 (BETWEEN)

语法含义示例
BETWEEN A AND B范围(含边界)WHERE age BETWEEN 20 AND 30
SELECT 字段1, 字段2, ……  
FROM 表名 
WHERE 字段 BETWEEN 最小值 AND 最大值;
e.g.
-- 找出 年龄在 20 到 30 岁之间(含边界) 的用户。
SELECT id, name, age 
FROM users 
WHERE age BETWEEN 20 AND 30;

(3) 集合判断 (IN / NOT IN)

语法含义示例
IN (值1, 值2, ...)属于集合WHERE city IN ('北京','上海')
NOT IN (值1, 值2, ...)不属于集合WHERE role NOT IN ('游客','游客2')
SELECT 字段1, 字段2, ……  
FROM 表名 
WHERE 字段 IN (值1, 值2, 值3);
e.g.
-- 查询 城市在北京或上海的用户。
SELECT id, name, city 
FROM users 
WHERE city IN ('北京', '上海');

-- 排除游客和未认证用户,只保留正式用户。
SELECT id, name 
FROM users 
WHERE role NOT IN ('游客', '未认证');

(4) 空值判断 (IS NULL / IS NOT NULL)

语法含义示例
IS NULL字段为空WHERE phone IS NULL
IS NOT NULL字段不为空WHERE email IS NOT NULL
SELECT 字段1, 字段2, ……  
FROM 表名 
WHERE 字段 IS [NOT] NULL;

e.g.

-- 找出未填写手机号的用户。
SELECT id, name 
FROM users 
WHERE phone IS NULL;

-- 筛选出填写了邮箱的用户,用于发送通知或身份校验。
SELECT id, name, email 
FROM users 
WHERE email IS NOT NULL;

(5) 模糊匹配 (LIKE)

 首先,我们先来了解两个和LIKE相关的通配符:

   %: 表示任意 0 个或多个字符。可匹配任意类型和长度的字符,有些情况下若是中文,请使用两个百分号(%%)表示。

   _: 表示任意单个字符。匹配单个任意字符,它常用来限制表达式的字符长度语句。

语法含义示例
LIKE '%值%'包含某内容WHERE name LIKE '%张%'
LIKE 'A%'以 A 开头WHERE name LIKE 'A%'
LIKE '%B'以 B 结尾WHERE name LIKE '%B'
LIKE '_强'第二个字是“强”WHERE name LIKE '_强'
LIKE '张_'“张”开头,两字名WHERE name LIKE '张_'
LIKE '张__'“张”开头,三字名WHERE name LIKE '张__'
LIKE '__强'三字名,以“强”结尾WHERE name LIKE '__强'
LIKE 'A__B'A 开头,B 结尾,共四字符WHERE code LIKE 'A__B'
NOT LIKE '%测试%'不包含“测试”的记录WHERE title NOT LIKE '%测试%'
SELECT 字段1, 字段2, ……
FROM 表名 
WHERE 字段 LIKE '匹配模式';
e.g.
-- 查询所有 名字以“张”开头 的用户,比如“张三”、“张小龙”、“张飞”。
SELECT id, name 
FROM users 
WHERE name LIKE '张%';

-- 查询所有 名字只有两个字,第二个字是“强” 的用户,比如“李强”、“王强”。
SELECT id, name 
FROM users 
WHERE name LIKE '_强';

(6) 多条件组合 (AND / OR / XOR)

  AND:

   1.所有条件必须都为 TRUE,结果才会返回;

   2.逻辑上相当于“交集”;

   3.可连续多次使用:a AND b AND c;

   4.可结合括号:(a AND b) AND (c OR d)

SELECT 字段列表
FROM 表名
WHERE 条件1 AND 条件2;
e.g.
-- 查询所有年龄 ≥18 且 城市是“北京”的用户。
SELECT id, name, age
FROM users
WHERE age >= 18 AND city = '北京';

  OR:

   1.只要任意一个条件为 TRUE,就会返回;

   2.逻辑上相当于“并集”;

   3.多个 OR 条件建议加括号,避免优先级误判

SELECT 字段列表
FROM 表名
WHERE 条件1 OR 条件2;
e.g.
-- 查询所有城市是“北京”或“上海” 的用户。
SELECT id, name, age
FROM users
WHERE city = '北京' OR city = '上海';

-- 找出在北京或上海,且年龄 ≥ 25 岁 的用户。
SELECT id, name, age
FROM users
WHERE (city = '北京' OR city = '上海')
AND age >= 25;

  XOR:

   1.XOR 是“互斥或”;

   2.适用于互斥条件判断;

SELECT 字段 
FROM 表 
WHERE 条件1 XOR 条件2;
e.g.
-- 只返回那些:年龄小于 30 的男性 或 年龄大于等于 30 的女性,仅满足其中一个条件时才返回,两个都满足或都不满足都不行。
SELECT id, name 
FROM users
WHERE (age < 30) XOR (gender = 'female'); 

3. ORDER BY 排序结果

 通过上面的学习,我们已经可以对我们的查询结果增加一些限制,我们遵循由简入繁的学习规则,先学会对我们的搜索结果进行排序。

SELECT 字段1, 字段2
FROM 表名
[WHERE 条件]
ORDER BY 字段 [ASC|DESC];

  其中,ORDER BY有两个参数:

   ASC:升序(默认)→ 小到大、A-Z、旧到新

   DESC:降序 → 大到小、Z-A、新到旧

e.g.
-- 查询用户列表,并按年龄从小到大排序显示。
SELECT id, name, age
FROM users
ORDER BY age ASC;

-- 查询用户列表,最新注册的用户排在最前面。
SELECT id, name, created_at
FROM users
ORDER BY created_at DESC;

-- 先按年龄升序排,如果年龄相同,再按成绩降序排。
SELECT id, name, age, score
FROM students
ORDER BY age ASC, score DESC;

4. LIMIT 限制返回条数(分页)

 通过上面的学习,我们已经可以对我们的查询按照某个或多个字段进行排序,接下来我们来学习一下限制查询结果以及分页查询。

SELECT 字段
FROM 表名
[WHERE 条件]
ORDER BY 字段
LIMIT 起始行, 返回条数;
e.g.
-- 找出成绩前五的学生
SELECT name, score
FROM students
ORDER BY score DESC
LIMIT 0, 5;

 其中,起始行这个参数可以帮助我们分页查询:起始行 = (page - 1) × pageSize

e.g.
-- 每页 5 条,显示第 3 页
SELECT id, name
FROM users
ORDER BY created_at DESC
LIMIT 10, 5;  -- (3-1)*5 = 10

5. 聚合函数 (Aggregate Functions)

 在学习GROUP BY之前,我们先来了解一下聚合函数,其实际意义是将多行数据“压缩”为一个统计结果,它是GROUP BY的核心搭档,配合 GROUP BY,就可以实现“每组一个统计”。

函数功能示例含义
COUNT()计数COUNT(*)统计所有行数
COUNT(distinct)统计非重复行
COUNT(字段)统计该字段非空的行数
SUM()求和SUM(字段)计算该字段总和
AVG()平均值AVG(字段)计算该字段平均值
MAX()最大值MAX(字段)统计最大值
MIN()最小值MIN(字段)统计最小值
SELECT COUNT(*) / SUM(字段) / AVG(字段) / MAX(字段) / MIN(字段)
FROM 表名;
e.g.
-- 查询公司中最高薪资是多少。
SELECT MAX(salary) AS highest_salary
FROM employees;

6. AS 别名

 在刚才的例子中,我们应该可以看到,在使用聚合函数之后使用了“AS”,这是 SQL 中一个非常常用、非常实用的小关键词,如果没有AS,在上面例子的输出结果中,我们使用聚合函数生成的新字段名会保留“MAX(salary)”,这是一个不易读的字段名,因此我们引入 AS , 给一个变量取个更好理解的名字。

SELECT 字段名 AS 别名
FROM 表名 AS 表别名;
e.g.
-- 计算所有女性用户的平均年龄。
SELECT AVG(age) AS average_age
FROM users
WHERE gender = 'female';

7. GROUP BY 分组统计

  GROUP BY 是用来把数据按某个字段进行分组,通常配合 聚合函数(COUNT、SUM、AVG…) 使用。

 注意,所有非聚合字段必须出现在 GROUP BY 子句中

SELECT 分组字段, 聚合函数
FROM 表名
[WHERE 条件]
GROUP BY 分组字段;
简单示例
-- 按部门分组,计算每个部门的平均工资。
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
加入 WHERE 条件:先过滤再分组
-- 统计 18 岁及以上用户 中,男女用户的数量。
SELECT gender, COUNT(*) AS count
FROM users
WHERE age >= 18
GROUP BY gender;

ROLLUP

  ROLLUP 是 GROUP BY 的增强语法,用于在分组统计的基础上,自动增加“小计”或“总计”行。
  如果存在多个分组, 则按照字段从左到右汇总
e.g. GROUP BY city, gender WITH ROLLUP: 先按 city + gender 分组, 然后对 city 做汇总(即每个城市合计),最后做整体汇总(总计)
SELECT 分组字段, 聚合函数
FROM 表
GROUP BY 分组字段1, 分组字段2 WITH ROLLUP;
e.g. 统计每个城市、性别的用户数量,并做小计和总计
SELECT city, gender, COUNT(*) AS user_count
FROM users
GROUP BY city, gender WITH ROLLUP;
结果如下:
 注意,ROLLUP 结果中的NULL表示“合计行”
citygenderuser_count
北京F120
北京M100
北京NULL220 ← 北京总计
上海F80
上海M70
上海NULL150 ← 上海总计
NULLNULL370 ← 所有城市总计

8. HAVING 分组后的条件过滤

 在 SQL 中:WHERE 是 分组前的条件 (过滤原始数据); HAVING 是分组之后的条件(过滤聚合结果)

SELECT 分组字段, 聚合函数
FROM 表名
[WHERE 行过滤条件]
GROUP BY 分组字段
HAVING 聚合函数筛选条件;
简单示例
-- 筛选平均工资超过 8000 的部门
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 8000;
多个分组后再加 HAVING
SELECT city, gender, COUNT(*) AS total
FROM users
GROUP BY city, gender
HAVING total >= 50;

现在我们来个综合例子来总结一下截止目前我们所学习到的内容

e.g. 统计所有年龄在 18 岁及以上的用户,按城市分组,计算每个城市的用户数量和平均工资,筛选出用户数不少于 5 的城市,并按平均工资从高到低排序,最终返回前 5 个城市。
 SELECT 
    city AS 城市,
    COUNT(*) AS 用户数,
    AVG(salary) AS 平均工资
FROM users
WHERE age >= 18
GROUP BY city
HAVING COUNT(*) >= 5
ORDER BY 平均工资 DESC
LIMIT 0, 5;

截止目前,我们已经完成了全部的单表查询必备要素。

接下来我们可以继续学习多表查询的内容:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值