整理一下之前的学习记录
1 基础
DISTINCT 去重
ORDER BY (DESC)【最后对数据排序,所以要先筛选WHERE】
WHERE = != < >= BETWEEN IS NULL 【如果对WHERE后的值进行修改:a+1, 强制类型转换,会导致索引失效】
AND OR 条件判断
执行顺序:[1] OR [2] AND [3] 会先执行AND 再 OR 所以需要加()
IN (合法值1,合法值2) 本质等于 合法1 OR 合法2
NOT IN 不存在
通配符
LIKE
% 任意字符出现任意次数 例:找到 查询 开头的数据:SELECT… WHERE xxx LIKE ‘查询%’ 类比正则 .*
_ 匹配任意字符 1次 例:找到 ID 为20x 的数据(200-209) SELECT … WHERE ID LIKE ‘20_’ 类比正则.
REGEXP (使用正则表达式)
WHERE column REGEXP ‘pattern’
pattern可能得选择如下:
. 任意
| or
[] 范围
\- 范围
\\ 转义、引用\\n
? 0或1次
{n} n次
^ $ 定位符号
计算字段 (都用于select中,为不存在的字段1)
连接 concat(列1,‘–’,列2)期间可以插入字符
别名 AS
支持基础运算 ±*/
2 函数
如之前的concat(拼接) RTrim(去空格)
Upper()大写
Lower()小写
时间 Date()
要使用yyyy-mm-dd的形式
找某一天要用 select * from table1 where Date(order_day) == ‘2025-05-08’
找月份可以 。。。 where year(order_day) = 2025 and month(order_day) = 05
数字处理 abs() rang() mod().…
汇总数据
聚集函数(找长度、求和、最值)count() sum() max() min()
可以同时使用多个函数
3 分组数据
计算某一标签的用例数量
select count(*) from 表名 where 列 = ‘xxx,’;
count() count(列)——通常使用会有优化,会使用索引。但差异通常很小。.
group by 依据某一列分组查询行数(查看用例标签都有多少用例)
select xx, count(*) from 表 group by 列 limit 10;
在group by之后计算了count(*) 后,如果要筛选不能用WHERE 要用HAVING
注意
- 1、使用group by要求select中的所有列都要体现在group by 后,
- 2、如果只是想展示某一列而不像用来分组,要使用聚合函数包围该列如max()
- 3、不建议关闭only_full_group_by模式
在分组之后希望进行筛选,要使用HVING
4 子查询
需要连续查询时
结果1 : 查询 xxx from xxx where xxx
结果2 : 查询 xxx from xxx where 结果1
结果2 : 查询 xxx from xxx where 结果2
可以使用() 嵌套查询,但实际会执行3次操作
查询 xxx from xxx where xxx in (查询 xxx from xxx where 【得到结果2】(查询 xxx from xxx where xxx 【得到结果1】))
作为计算的子查询
表1存放测试套件
表2存放测试用例
想要得到表1对应的表2有多少用例:
select 列1, 列2, (select count(*) from 表2 where 表2.列 = 表1.列) as xx_count from 表1;
注意这里需要 【完全限定类名】,否则如果列名重名会出现错误
5 联结
供应商、商品的关系,存在两个数据表中,如果重复在商品表中存储供应商的信息,会浪费空间与难以管理(每次输入供应商信息要一致)。
所以在 商品 表中存储 供应商 表的id(主键)其他信息不存储,这样就通过供应商表的id 关联了两个数据库表
这时候, 供应商id(主键)叫做 商品表中的外键提升了 可伸缩性
在一条SELECT中查询:
FROM中写了两个表,要在WHERE中确定两个表的联结关系(这时候要写【完全限定类名】)
select 列1, 列2, 列3 from 表2, 表1 where 表2.xx= 表1.学习order by 学习limit 10;
如果没有在WHERE中确定联结关系,这会按“笛卡尔积”的方式进行显示(第1个表的行数 * 第二个表的行数)
不用WHERE的联结写法——内部联结 强烈推建
1 语法逻辑不同
INNER JOIN:显式声明了 “表之间的联结关系”,通过 ON 子句明确指定联结条件,逻辑上更贴近 “先关联表,再过滤结果” 的过程。
WHERE 隐式联结:通过 FROM 子句并列多个表(逗号分隔),然后在 WHERE 中用条件模拟联结,逻辑上更像 “先笛卡尔积所有表,再过滤无效行”。
2 可读性与可维护性
INNER JOIN:结构清晰,联结条件(ON)和过滤条件(WHERE)分离,尤其在多表联结时(如 3 张以上表关联),能明确看到每张表的关联关系。
WHERE 隐式联结:所有条件混杂在 WHERE 中,需从大量条件中区分哪些是联结条件、哪些是过滤条件,复杂查询中可读性差。
3 对 “外联结” 的兼容性
INNER JOIN 是显式联结语法的一部分,可轻松扩展为 LEFT JOIN/RIGHT JOIN 等外联结(保留某表全部行)。
WHERE 隐式联结 无法直接表达外联结逻辑。例如,若试图用 WHERE 模拟 LEFT JOIN,可能意外过滤掉 “主表无匹配的行”(因为 WHERE 条件会强制过滤所有不满足条件的行)。
同理可以联结多个表:
6 高级联结
表别名:
在FROM后给表都起了别名:可以缩短sql长度
不同的联结
自联结:
想知道 同在一张表中的 某一生产物的供应商的其他生产物品:
使用子查询:
SELECT 产物id, 产物名 FROM 产品表 WHERE (SELECT 供应商id FROM 产品表 WHERE 产物id = '某一生产物');
使用自联结:
SELECT 产物id, 产品名 FROM 产品表 as p1, 产品表 as p2 WHERE p1.供应商id = p2.供应商id AND p2.产物id = '某一生产物';
产品表出现了两次,要使用表别名重新命名,再通过WHERE子句联结。
外联结:
[LEFT/ RIGHT] OUTER JOIN
例如学生表记录学生,成绩表记录成绩,现在要查询学生的成绩
SELECT s.name, sc.subject, sc.grade FROM student s LEFT JOIN score sc ON s.id = sc.student_id;
使用左查询会让学生的记录全在,而就算没有对应的成绩也会显示未null
反之,右查询会让成绩的记录在,而没有对应学生的会显示null
联结中使用聚合函数
select a.列1, count(b.列2) as xx FROM 表1 as a LEFT OUTER JOIN 表2 as b ON a.xx=b.xx GROUP BY a.xx;
7 组合查询
UNION组合结果,
select * from b1 where xx='xx'
union
select * from 表2 where xx='xx' limit 10;
等效于使用 xx='xx' OR xx='xx'
UNION查询结果自动去除重复行,
UNION ALL不会。
注意组合查询后ORDER BY只能在结尾用一条,不能分别排序
8 全文本搜索
对比:1 比LIKE REGEXP效率高,他们要全表扫描,而这个使用了索引。
2 它会进行优先级判断,例如搜索的内容出现的多次的(出现很多次搜索的“你好”),会排序在最前面
要求:索引被搜索的列,创建使用 FULLTEXT 搜索用Match()Against()
创建表:
CREATE TABLE xxx
(
xxx_id int NOT NULL AUTO_INCREMENT,
xxx_date datetime NOT NULL,
xxx_text text NOT NULL,
PRIMARY KEY(note_id),
FULLTEXT(note_text)
)ENGINE=MyISAM;
FULLTEXT后,mysql会自动维护索引(自动更新)
使用:
SELECT not_text
FROM xxx
WHERE Match(xxx_text) Against('aabb');
在SELECT使用:
SELECT xxx_text, Match(xxx_text) Against('你好') AS rank
FROM xxx;
返回所有的行,rank为计算出来的优先值
9 插入数据
INSERT 插入一行
INSERT INTO customers(列1,
列2,
li3,
...)
VALUES('1',
'2',
...)
可也不指定列名省略customers后的括号,但是要一一对应填写。
小知识:id int not null auto_increment 这样的列,会有默认值,可以填null后自动添加。
提交多条:
INSERT INTO customers(列1,
列2,
li3,
...)
VALUES('1',
'2',
...
),
('1',
'2',
...
),
插入检索出的数据
INSERT SELECT
10 更新
UPDATE 表名
SET 列名 = 'xxx'
WHERE xx='xx';
删除列的值,可以设置成NULL
11 删除
DELETE FROM 表名
WHERE xx=xx;
尽量不要使用不带WHERE
子句的删除与修改,否则是操作每一行