MySQL系列(5): 常用SQL,压缩备份还原
整理下以前记录的一些常用但一时想不起的 SQL 语句,有些极其简单,有些则需要思考下。
常规 SQL
根据其它表的条件更新:
1
2update users u, score s SET s.`isConsumer` = 1
where s.`userId` = u.`aqUserid` and u.`aqRoleId` = 16;查询存在重复的数据
1
2
3select id,name,phone_number from tbu_user
group by phone_number
having count(phone_number) > 1;删除表中重复数据,只保留一条
1
2
3
4DELETE FROM users_bank
WHERE id NOT IN (
SELECT minid FROM (
SELECT MIN(id) AS minid FROM users_bank GROUP BY userId) b);删除同一张表里查出的数据, 使用中间表
1
2
3
4
5
6
7
8
9DELETE FROM tbu_user WHERE id IN (
SELECT temp.id FROM (
SELECT id FROM tbu_user u WHERE u.`id` NOT IN (
SELECT user_id FROM tbu_user_result)) temp);
DELETE FROM business WHERE userId IN (
SELECT t.userId FROM (
SELECT b.`userId` FROM business b,users u
WHERE b.`userId` = u.`aqUserid` AND u.`aqRoleId` != 15) t);内联接实现分组取最大ID或最大时间的值
1
2
3
4
5SELECT * FROM tbs_reg_count t WHERE t.id IN (SELECT MAX(id)
FROM tbs_reg_count t WHERE create_datetime
BETWEEN DATE_FORMAT('2018-11-23 00:00:00','%Y-%m-%d 00:00:00')
AND DATE_FORMAT('2018-11-24 00:00:00','%Y-%m-%d 23:59:59')
GROUP BY sys_user_id, DATE_FORMAT(create_datetime,'%Y-%d-%m'));查时间范围是否有交集或包含
1
2
3
4SELECT * FROM tbs_price WHERE sys_user_id = 1 AND
(((start_datetime < '2018-11-21 10:00:00') AND (start_datetime > '2018-11-18 10:00:00')) OR
((end_datetime > '2018-11-18 10:00:00') AND (end_datetime < '2018-11-21 10:00:00')) OR
((start_datetime > '2018-11-18 10:00:00') AND (end_datetime) < '2018-11-21 10:00:00'));避免 sum() 函数 NPE 问题
当某一列的值全是NULL时,count(col)的返回结果为0,但sum(col)的返回结果为NULL,因此使用sum()时需注意 NPE 问题。1
SELECT IF(ISNULL(SUM(pay_money)),0,SUM(pay_money)) FROM tbu_auth_order;
插入从其它表查询到的数据
1
2insert into sys_role_menu(roleid,roleName,menuid,menuName)
select sys_role.`id`,sys_role.`roleName`,sys_menu.`menu_id`,sys_menu.`menu_name` from sys_role,sys_menu;
NOT IN
注意:MySQL 的 NOT IN 查询值中不能存在 NULL 值,否则结果会一直为空。大 NOT IN 的查询子句里增加非空判断。
1 | select * from student where name not in ( |
GROUP BY
1 | -- 分组查询:group by |
压缩备份与还原
- 压缩备份:导出整个数据库
1
2
3
4
5
6
7mysqldump -u root -p 123 > xxxx.sql
-- 压缩导出
mysqldump -u root -p 123| gzip > db_name2017070802.sql.gz
-- 导出表数据,db_name:数据库名;sys_user:表名
mysqldump -u root -p db_name sys_user > sys_user.sql - 备份还原
1
2
3
4
5-- 压缩 sql 文件还原
gunzip < anqi2017070802.sql.gz | mysql -uroot -p db_name
-- sql 文件还原
mysql -u admin -p 123 < /data/mysql_backup/xxx.sql - 导出数据表结构
1
mysqldump -uroot -p -d db_name > db_name.sql
- 导入数据库表结构
1
2
3
4mysql -uroot database < db_name.sql
mysql>use db_name
mysql>source db_name.sql - 导出到 XML 文件
1
mysql -u user_name -xml -e 'SELECT * FROM table_name' > table_name.xml
其它注意项
- count(distinct col) 计算该列除 NULL 之外的不重复行数,注意 count(distinct col1, col2) 如果其中一列全为 NULL,那么即使另一列有不同的值,也返回为 0。
- 不要使用 count(列名) 或 count(常量) 来替代
count(*)
,count(*) 是SQL92定义的标准统计行数的语法,跟数据库无关,跟 NULL 和 非NULL 无关。
count(*) 会统计值为NULL的行,而 count(列名) 不会统计此列为 NULL 值的行。 - 在 varchar 字段上建立索引时,必须指定索引长度,通常情况下,长度为
20
的索引,区分度会高达 90% 以上。
可以使用 count(distinct left(列名, 索引长度))/count(*) 计算区分度来确定索引长度。 - 利用延迟关联或者子查询优化超多分页场景
MySQL 的分页查询关键字:limit offset,rows
;
MySQL并不是跳过offset
行,而是取offset+N
行,然后返回放弃前 offset 行,返回N
行,那当 offset 特别大的时候,效率就非常的低下,要么控制返回的总页数,要么对超过特定阈值的页数进行 SQL 改写。
正例:先快速定位需要获取的 id 段,然后再关联:SELECT a.* FROM tb1 a, (select id from tb1 where … LIMIT 100000,20) b where a.id=b.id - MySQL limit 与 offset
1
2
3
4
5
6-- limit,下例,从第 2 行数据开始读取 1 行。注意,MySQL 行索引(偏移起始位)是从 0 开始。
-- limit m, n; 表示从第 m 行索引位置开始读,读 n 条数据。
select * from order where user_id = 100 limit 2,1;
-- offset,下例,指偏移 1 行数据,读取 2行。
select * from order where user_id = 100 limit 2 offset 1;
相关参数
MySQL系列(5): 常用SQL,压缩备份还原