select 查询
1. 关键字顺序编写
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
2. SELECT 语句执行顺序
FROM 表 > WHERE 条件 > GROUP BY 分组 > HAVING 筛选分组 > SELECT 字段 > DISTINCT > ORDER BY 排序 > LIMIT 查询数量
执行顺序举例:
SELECT DISTINCT
player_id,
player_name,
count(*) AS num # 顺序 5
FROM
player
JOIN team ON player.team_id = team.team_id # 顺序 1
WHERE
height > 1.80 # 顺序 2
GROUP BY
player.team_id # 顺序 3
HAVING
num > 2 # 顺序 4
ORDER BY
num DESC # 顺序 6
LIMIT 2 # 顺序 7
3. limit 的使用
在实际系统中定义 select
查询语句时,应加上 limit
限制查询数据条数。
- 一是防止查询数据过多,导致慢 SQL 语句的产生。
- 二是保证查询的数据条数正常。
特殊情况:
- 在使用分页工具时可不考虑,因为分页工具一般会拦截查询请求并对语句进行拼接
- 要求查询全部数据的查询也尽可能地预估其数据量并加上
limit
,除非数据量不可知
4. 展示列表、分页查询应加上 order by
- 在分页查询时,有可能会出现同一条数据出现在不同页上、同一页的多次查询结果不一等情况 。这是由于数据库查询结果有可能因为插入或更新操作导致存储顺序不稳定。
- 因此,应当在查询结果匹配数量较大的分页查询语句中,加上
order by
。并提供一个能确定唯一数据行的字段用以排序,如主键、唯一约束键。 - 若该查询允许用户提供排序键,则应当将自定义排序字段放在唯一字段前。
5. 使用 selectOne 要防止为 null
- 在 MyBatis 中使用
selectOne
查询时,需要防止出现查不到数据的情况。 - 当 SQL 语句查询为空时,
selectOne
函数会返回null
。若用一个对象变量来接他的返回值,需要先判断他是否为null
后再对其进行对象操作,防止出现空指针异常导致程序无法继续正常运行。 - 技巧:在 Java 中可使用以下语句来简便对
null
的排除:
TestClass testClass = Optional.ofNullable(testClass).orElse(new TestClass());
6. 查询某数据是否存在:性能优化
- 惯性思维是使用
count
函数计算结果来判断是否存在,但是这个操作会统计全表,在数据量大的表中耗时极高。 - 可以用
select 1 limit 1
来判断是否存在,当数据库找到符合的数据时就会结束查询,不会统计全表。在 MyBatis 中,可以使用selectOne
调用该 SQL 语句,并使用Integer
包装类来接收返回值,通过判断返回是否为null
来判断是否存在。若使用基础类型int
可能会导致程序报错。 例子:
# SQL, id=hasClassStu
SELECT
1
FROM
student
WHERE
class_id = '1'
LIMIT 1;
// Java
return session.selectOne("hasClassStu") != null;
7. SQL 函数、计算应该只在条件值上使用
- SQL 函数、计算应该只在条件值上使用,即
where
条件中=
的右边。 - 若给数据库字段使用 SQL 函数、或进行计算会使得索引失效,因为这需要给全表的指定字段的所有值都进行计算后才能和条件比对。 正确例子:
SELECT
id,
stu_name,
age
FROM
student_info
WHERE
age = 2020 - #{year};