My SQL常用优化增改删

  1. explain获取对应的执行计划
题目描述
获取select * from employees对应的执行计划

explain模拟优化器执行SQL语句,在5.6以及以后的版本中,除过select,其他比如insert,update和delete均可以使用explain查看执行计划,从而知道mysql是如何处理sql语句,分析查询语句或者表结构的性能瓶颈。
作用
1、表的读取顺序
2、数据读取操作的操作类型
3、哪些索引可以使用
4、哪些索引被实际使用
5、表之间的引用
6、每张表有多少行被优化器查询
原文链接:http***log.csdn.net/jiadajing267/article/details/81269067

  1. concat、group_concat 组合
将employees表的所有员工的last_name和first_name拼接起来作为Name,中间以一个空格区分
select CONCAT(last_name,' ',first_name) as Name
from employees; 

解题思路:①不同字符串连接方法不一样,在Mysql中,可以利用CONCAT()函数将多个字符串连接起来,中间用逗号隔开。②空格用’ '表示。

其他:

按照dept_no进行汇总,属于同一个部门的emp_no按照逗号进行连接,结果给出dept_no以及连接出的结果employees

select dept_no,group_concat(emp_no separator ',') as employees
from dept_emp
group by dept_no;

①连接同一列字段:group_concat( [distinct] <要连接的字段> [order by 排序字段 asc/desc ] [separator ‘分隔符’] ) 。分隔符可以选择省略,省略时默认为逗号,这里还是写出来了。另外还有一点需要注意,group_concat函数中的各个参数之间用空格隔开,不能用逗号隔开,不然会出错。
②按照dept_no进行汇总,所以要对dept_no进行分组。

3、创建一个名为xx的表:
在这里插入图片描述

create table actor(
actor_id smallint(5) not null,
first_name varchar(45) not null,
last_name varchar(45) not null,
last_update timestamp not null  default (datetime('now','localtime')),
PRIMARY KEY(actor_id)
);

使用默认值为系统时间:DEFAULT (datetime(‘now’,‘localtime’)));

4、批量插入数据:

解题思路:插入数据语法:insert into <表名> values (<数据1>,<数据2>…);

insert into actor values
(1,'PENELOPE','GUINESS','2006-02-15 12:34:33'),
(2,'NICK','WAHLBERG','2006-02-15 12:34:33');

5、insert、replace

insert into:插入数据,如果主键重复,则报错
insert repalce:插入替换数据,如果存在主键或unique数据则替换数据
insert ignore:如果存在数据,则忽略。

题目描述
对于表actor批量插入如下数据,如果数据已经存在,请忽略,不使用replace操作

INSERT OR IGNORE INTO actor VALUES (3, 'ED', 'CHASE', '2006-02-15 12:34:33');

6、根据题意,本题要用两条语句完成,先用 CREATE TABLE 语句创建actor_name表,包含first_name与last_name字段,然后用 INSERT INTO … SELECT … 语句向actor_name表插入另一张表中的数据,注意分号

CREATE TABLE actor_name
(
first_name varchar(45) NOT NULL,
last_name varchar(45) NOT NULL
);
INSERT INTO actor_name SELECT first_name, last_name FROM actor;

7、创建索引:

对first_name创建唯一索引uniq_idx_firstname,对last_name创建普通索引idx_lastname

给指定表或者视图的某列添加索引使用语句:CREATE [UNIQUE/…] INDEX indexName ON tableName(colName);

//创建唯一索引
CREATE UNIQUE INDEX uniq_idx_firstname on actor(first_name);
//创建普通索引
CREATE INDEX idx_lastname on actor(last_name);

8、creat view 创建视图

针对actor表创建视图actor_name_view,只包含first_name以及last_name两列,并对这两列重新命名,first_name为first_name_v,last_name修改为last_name_v:

注意 CREATE VIEW … AS … 的 AS 是创建视图语法中的一部分

CREATE VIEW actor_name_view (fist_name_v, last_name_v) AS
SELECT first_name, last_name FROM actor 

或者:

create view actor_name_view as
select first_name as first_name_v, last_name as last_name_v
from actor

9、强制索引查询:

针对salaries表emp_no字段创建索引idx_emp_no,查询emp_no为10005, 使用强制索引。

MySQL中,使用 FORCE INDEX 语句进行强制索引查询,可参考:

http://www.jb51.net/article/49807.htm

SELECT * FROM salaries FORCE INDEX idx_emp_no WHERE emp_no = 10005

10、列表中在xx列后新加一列:

用 ALTER TABLE … ADD … 语句可以向已存在的表插入新字段,并且能够与创建表时一样,在字段名和数据类型后加入NOT NULL、DEFAULT等限定,可参考:
http://www.runoob.com/sqlite/sqlite-alter-command.html

ALTER TABLE actor ADD COLUMN create_date datetime NOT NULL DEFAULT '0000-00-00 00:00:00'

11、exists :

IN:确定给定的值是否与子查询或列表中的值相匹配。in在查询的时候,首先查询子查询的表,然后将内表和外表做一个笛卡尔积,然后按照条件进行筛选。所以相对内表比较小的时候,in的速度较快。

EXISTS:指定一个子查询,检测行的存在。遍历循环外表,然后看外表中的记录有没有和内表的数据一样的。匹配上就将结果放入结果集中。

使用含有关键字exists查找未分配具体部门的员工的所有信息。

用 in :

SELECT * FROM employees WHERE NOT EXISTS 
(SELECT emp_no FROM dept_emp WHERE emp_no = employees.emp_no)

用 select :

SELECT * FROM employees WHERE emp_no NOT IN (SELECT emp_no FROM dept_emp)

12、limit /offset

分页查询employees表,每5行一页,返回第2页的数据

根据题意,每行5页,返回第2页的数据,即返回第6~10条记录,以下有两种方法可以解决:

方法一:LIMIT 后的数字代表返回几条记录,OFFSET 后的数字代表从第几条记录开始返回(第一条记录序号为0),也可理解为跳过多少条记录后开始返回。(当 limit和offset组合使用的时候,limit后面只能有一个参数,表示要取的的数量,offset表示要跳过的数量 。)

SELECT * FROM employees LIMIT 5 OFFSET 5

方法二::只利用 LIMIT 关键字。注意:在 LIMIT X,Y 中,Y代表返回几条记录,X代表从第几条记录开始返回(第一条记录序号为0),切勿记反。(当limit后面跟两个参数的时候,第一个数表示要跳过的数量,后一位表示要取的数量。)

SELECT * FROM employees LIMIT 5,5

13、update

Update 语句用于修改表中的数据。
UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值

题目:所有to_date为9999-01-01的全部更新为NULL,且 from_date更新为2001-01-01。

另外要注意若干列 to_date = NULL 和 from_date = ‘2001-01-01’ 之间只能用逗号连接,切勿用 AND 连接。

UPDATE titles_test SET to_date = NULL, from_date = '2001-01-01'
WHERE to_date = '9999-01-01';

例2 :

将所有获取奖金的员工当前的薪水增加10%。

update salaries set salary=salary*1.1 where emp_no in (
    select emp_no from emp_bonus
) and to_date='9999-01-01'

14、update replace :

题目:将id=5以及emp_no=10001的行数据替换成id=5以及emp_no=10005,其他数据保持不变,使用replace实现。

replace(字段,“需要替换的值”,“替换后的值”)

update titles_test set emp_no = replace(emp_no,10001,10005) where id=5

15、更改表名rename :

alter table tname_old rename to tname_new

将titles_test表名修改为titles_2017。

alter table titles_test(表名) rename titles_2017

16、substr 截取字符段

substr(字符串,起始位置,长度)
起始位置:截取的子串的起始位置(注意:字符串的第一个字符的索引是1)。值为正时从字符串开始位置 开始计数,值为负时从字符串结尾位置开始计数。
长度:截取子串的长度

获取Employees中的first_name,查询按照first_name最后两个字母,按照升序进行排列

SELECT first_name FROM employees ORDER BY substr(first_name,-2) 

MySQL 直接利用right函数:

SELECT first_name FROM employees ORDER BY RIGHT(first_name ,2);

17、设置触发器

构造一个触发器audit_log,在向employees_test表中插入一条数据的时候,触发插入相关的数据到audit中。

CREATE TRIGGER trigger_name trigger_time trigger_event ON tbl_name
FOR EACH ROW
BIGIN
trigger_stmt
END

1、trigger_name标识触发器名称,用户自行指定

2、trigger_time标识触发时机,可以为before或after

3、trigger_event标识触发事件,包括INSERT、UPDATE和DELETE

4、tbl_name标识建立触发器的表名,即在哪张表上建立触发器

5、trigger_stmt是触发器内容,触发器程序可以使用begin和end作为开始和结束,中间包含多条语句

本题SQLITE和MYSQL通用:

CREATE TRIGGER audit_log AFTER INSERT ON employees_test
FOR EACH ROW
BEGIN
INSERT INTO audit VALUES(NEW.ID,NEW.NAME);
END

18、delete

删除emp_no重复的记录,只保留最小的id对应的记录。

本题思路如下:先用 GROUP BY 和 MIN() 选出每个 emp_no 分组中最小的 id,然后用 DELETE FROM … WHERE … NOT IN … 语句删除 “非每个分组最小id对应的所有记录”

DELETE FROM titles_test WHERE id NOT IN 
(SELECT MIN(id) FROM titles_test GROUP BY emp_no)
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值