sql练习精讲系列
2.如何查找第N高的数据
有一张“成绩表”,包含学生编号,选修课程的编号和成绩信息。
现在需要找出某课程成绩第二高的学生成绩。这里以课程编号为“01”的同学为例。
如果不存在第二高成绩的学生,那么查询应返回 null。
- 利用ORDER BY排序,再利用Limit限制 offset偏移,排除只有1个值情况结合IFNULL
- 解释:先倒序排序去重,限制显示第二条,如果第二条是空,则返回空置(即不存在)
SELECT
IFNULL(
(SELECT DISTINCT 成绩
FROM 成绩
ORDER BY 成绩 DESC
LIMIT 1 OFFSET 1),
NULL) AS "01课程第二高的成绩";
-
从第n行取值:limit 1 offset 1 意为offset 1从第1行开始取(不包括第1行);limit 1限制1行。
问:limit 2, 1 和 limit 2 offset 1 的区别是什么?
答:limit 2, 1为 跳过2条取出1条数据,limit后面是从第2条开始读,读取1条信息,即读取第3条数 据 ;limit 2 offset 1从第1条(不包括)数据开始取出2条数据,limit后面跟的是2条数据, offset后面是从第1条开始读取,即读取第2,3条。 -
判断是否为null——ifnull函数: IFNULL(expression, alt_value)
如果第一个参数的表达式expression 为 NULL,则返回第二个参数的备用值。
176.第二高的薪水
select ifNull(
(select distinct salary
from Employee
order by Salary Desc
limit 1,1),null
) as SecondHighestSalary;
滴滴面试题
Employee 表包含所有员工信息,每个员工有其对应的 Id, Name,Salary 和 DepartmentId。Department 表包含公司所有部门的信息。编写一个 SQL 查询,找出每个部门工资第二高的员工。
/* 首先看子句中的WHERE DepartmentId = a.DepartmentId,表示子句会构造n(部门个数)个分区,再每个分区中找到第2高(order by + limit 1,1)薪水的人的ID。当然这里薪资有可能重复,为了结构的简便不在考虑,可以在子句中再次嵌套一个对薪资去重的子子语句。
*/
SELECT * FROM Employee a
WHERE Id =
(SELECT Id
FROM Employee
WHERE DepartmentId = a.DepartmentId
ORDER BY Employee.Salary desc
LIMIT 1,1)
如果使用窗口函数则简单的多
select Departmentid,Name,Salary,rn
from(select *,
row_number()over(PARTITION by Departmentid
ORDER BY Salary desc) as rn
from Employee)as a
WHERE rn=2
3.经典排名问题
下图是"01课程成绩"表中的内容,记录了每个学生学生编号,课程编号和成绩。现在需要根据成绩来排名,如果两个分数相同,那么排名要是并列的。
比如题目中的成绩从大到小排序应该是80,80,76,70,50,31。分数相同排名并列,那么6位同学的排序应该是1,1,3,4,5,6。
select *,
rank() over (order by 成绩 desc) as `rank`,
dense_rank() over (order by 成绩 desc) as dese_rank,
row_number() over (order by 成绩 desc) as row_num
from 成绩
rank():跳跃排序;同分并列,但会占用下一个排名名额。
dense_rank():连续排序;单词直译为密集排序。同分并列,不占用下一个排名名额。
row_number():没有重复值的排序(记录相等也是不重复的),可以进行分页使用。[窗口函数语法] 函数名([expr]) over 子句 :
over是关键字,用来指定函数执行的窗口范围,如果后面括号中什么都不写,则意味着窗口包含满足where条件的所有行,窗口函数基于所有行进行计算;如果不为空,则支持以下四种语法来设置窗口:
select * from
( select row_number()over w as row_num,
order_id,user_no,amount,create_date
from order_tab
WINDOW w AS (partition by user_no order by amount desc)
)t ;
window_name:给窗口指定一个别名,如果SQL中涉及的窗口较多,采用别名可以看起来更清晰易读。上面例子中如果指定一个别名w,则改写如下:
partition子句:窗口按照那些字段进行分组,窗口函数在不同的分组上分别执行。上面的例子就按照用户id进行了分组。在每个用户id上,按照order by的顺序分别生成从1开始的顺序编号。 order by子句:按照哪些字段进行排序,窗口函数将按照排序后的记录顺序进行编号。可以和partition子句配合使用,也可以单独使用。上例中二者同时使用,如果没有partition子句,则会按照所有用户的订单金额排序来生成序号。
frame子句:frame是当前分区的一个子集,子句用来定义子集的规则,通常用来作为滑动窗口使用。比如要根据每个订单动态计算包括本订单和按时间顺序前后两个订单的平均订单金额,则可以设置如下frame子句来创建滑动窗口:
[窗口函数汇总]
CUME_DIST(): 函数计算一组值中的值的累积分布。
LAG(): 对当前行之前的指定物理偏移量的行的访问。
LEAD(): 对当前行之后的指定物理偏移量的行的访问。 NTILE(): 有序分区的行分配到指定数量的大致相等的组或桶中。
PERCENT_RANK(): 函数计算结果集的分区中值的相对位置。 DENSE_RANK() RANK() ROW_NUMBER()
找出支付金额在累计前20%的用户
现有交易数据表user_sales_table如下:
user_name 用户名
pay_amount 用户支付额度
找出支付金额在累计前20%的用户。
/*
ntile(5) over(order by sum(pay_amount) desc) as level 按照支付金额累计倒序排列后分成大致相同的5组。
*/
select b.user_name from
(select
user_name,
ntile(5) over(order by sum(pay_amount) desc) as level -- 分成5组
from user_sales_table group by user_name ) b
where b.level = 1
4.连续出现N次类问题
下面是某班级学生的某课程的成绩表(表名Sscore,列名:学号、成绩),使用SQL查找所有至少连续出现3次的成绩。
select distinct a.成绩 as 连续出现3次的成绩
from Sscore as a,
Sscore as b,
Sscore as c;
where a.学号 = b.学号 - 1
and b.学号 = c.学号 - 1
and a.成绩 = b.成绩
and b.成绩 = c.成绩;
180. 连续出现的数字
1.使用变量。
首先假设变量pre为前一位同学的成绩,默认值为null,变量cnt为重复出现某个成绩的数目,默认为0。
取第一行,a.成绩 = 当前行成绩 ----> 判断与pre是否相等, 如果相等,则cnt = cnt+1, 若不相等,则cnt = 1, ----> pre = a.成绩。
遍历到下一行(即第2行),重复步骤2,步骤2中的取第1行变为取读2行…
最后判断cnt大于等于3的成绩;并去重。
SELECT DISTINCT t.num, MAX(cnt)
FROM
(SELECT a.num,
@cnt := if(@pre = a.num, @cnt+1, 1) cnt, -- 最后的cnt,pre起到命名的作用
@pre := a.num pre
FROM (SELECT * FROM logs ORDER BY num) a, -- 注意这里的order排序,根据题意决定是否加上。区别在需不需要重新排列。
(SELECT @pre = null,
@cnt = 0
) b
) t
WHERE t.cnt >= 3
GROUP BY t.num;
2.窗口函数
SELECT num, max(num_rk) AS num_cnt
FROM
(SELECT num, row_number()over(PARTITION BY num) AS num_rk -- 先计算出排名
FROM logs) t
GROUP BY t.num -- 根据最大的排名来知道num的出现次数
HAVING num_cnt >= 3; -- 用排名进行筛选
[知识点讲解] [变量分类]
用户自定义变量 局部变量 会话变量 系统变量 会话变量 全局变量 这里主要讲用户自定义变量。
[什么是用户自定义变量]
用户自定义变量是一个用来存储内容的临时容器,在连接MySQL的整个过程中都存在,可以使用下面的SET和SELECT语句来定义它们:
mysql> SET @one := 1;
mysql> SET @min_actor := (SELECT MIN(actor_id) FROM sakila.actor);
mysql> SET @last_week := CURRENT_DATE - INTERVAL 1 WEEK;
[变量使用场景] 作为循环计数器来计算循环执行的次数。 保持要通过控制流语句(如WHILE)进行测试的值。 存储函数或存储过程返回的值。
> [书写模板拆解]
> 变量存放位置
> # 生成变量 pre, cnt 并默认为 null,0.
> select @pre := null,@cnt := 0
> 迭代写法
> # 某一次的迭代写法.
> @cnt := if(@pre = a.Num, @cnt + 1, 1) cnt,
> -- 先判断上一行的num和当前行的num是否一样,如果一样,说明上下行的数字一样则变量@cnt+1,如果不一样,则cnt还是为1.
> @pre := a.Num pre
> -- 遍历,将当前行的num赋值给pre,然后进入判断下一行
大厂面试真题
统计连续登陆的三天数和以上的用户以及他们的首次登录和最后登陆时间
select
uid,min(dt),max(dt),count(1) as counts
from
(
select
uid ,dt, date_sub(dt,rn) as dis
from
(
select
uid ,dt,row_number()over (partition by uid order by dt)rn
from continuous
)t1
)t2
group by uid ,dis
having counts>2
5.主键不相同的多表联合查询
1.明确连接方式 要求找出课程成绩大于课代表成绩的所有同学的学生编号和成绩。我们可以使用自连接两张表。
2.确定连接两表的主键 课代表编号代表作为课代表的某位同学的编号,它是某位同学的学生编号。所以a.学生编号=b.课代表编号
另外还需要判断不是课代表的同学的成绩需要大于课代表的成绩。所以a.成绩 > b.成绩
SELECT
a.学生编号 as 成绩大于课代表成绩的学生编号
FROM Sscore AS a JOIN Sscore AS b
ON a.课代表编号 = b.学生编号
AND a.成绩 > b.成绩
181.超过经理收入的员工
Employee 表包含所有员工,他们的经理也属于员工。每个员工都有一个 Id,此外还有一列对应员工的经理的 Id。
给定 Employee 表,编写一个 SQL 查询,该查询可以获取收入超过他们经理的员工的姓名。在上面的表格中,Joe
是唯一一个收入超过他的经理的员工。
SELECT
a.NAME AS Employee
FROM Employee AS a JOIN Employee AS b
ON a.ManagerId = b.Id
AND a.Salary > b.Salary;
6.查找重复类问题
编写一个SQL查询,查找学生表中所有重复的学生的名字。
select 姓名 from
(select 姓名, count(姓名) as 出现次数
from Sstudent
group by 姓名
where a.出现次数 > 1) a
# having用法
select 姓名, count(姓名) as 出现次数
from Sstudent
group by 姓名
having 出现次数 > 1
[having与where的区别]
having 子句的作用是筛选满足条件的组,即在分组之后过滤数据,条件中经常包含聚组函数,使用having
条件显示特定的组,也可以使用多个分组标准进行分组。 与 WHERE 和 SELECT 的交互方式类似。WHERE
搜索条件在进行分组操作之前应用;而 HAVING 搜索条件在进行分组操作之后应用。
[SQL语句执行顺序]
sql语法的分析是从右到左,也可以理解为从里到外。 SQL Select语句完整的执行顺序:
from子句组装来自不同数据源的数据; where子句基于指定的条件对记录行进行筛选; group by子句将数据划分为多个分组;
使用聚集函数进行计算; 使用having子句筛选分组; 计算所有的表达式; select 的字段; 使用order by对结果集进行排序。
SQL语言不同于其他编程语言的最明显特征是处理代码的顺序。在大多数据库语言中,代码按编码顺序被处理。但在SQL语句中,第一个被处理的子句式FROM,而不是第一出现的SELECT。在这里我们看到上面不能使用group by + where 而是使用group by + having,原因便在于执行顺序where >
group by + having。
7.查找不在表里的数据
select a.姓名 as 未选课学生姓名
from Sstudent a left join Sstudent_choose b
on a.学生编号 = b.学生编号
where
b.学生编号 is null;
183.从不订购的客户
select a.Name as Customers
from Customers as a
left join Orders as b
on a.Id=b.CustomerId
where b.CustomerId is null;
select customers.name as 'Customers'
from customers
where customers.id not in
(
select customerid from orders
);
用SQL提取用户首次下单的信息(金额、时间)
用户第一单购买的行为往往反映了用户对平台的信任度和消费能力。现在数据库中有一张用户交易表order,其中有userid(用户ID)、amount(消费金额)、paytime(支付时间),请写出对应的SQL语句,查出每个用户第一单的消费金额。
知道order表有3个字段:userid、amount、paytime,求出每个用户第一单的消费金额。笔者稍微研究了一下就得出了一个答案。逻辑:先找出每个用户第一单的消费时间,然后对应userid和paytime匹配相应的amount即可。
select o.userid,o.amount,ump.mp
from (select userid,min(paytime) as mp from use_order group by userid) as ump
join user_order as o on ump.mp=o.paytime order by userid;
瑕疵就是,如果不同用户的paytime有相同的,那么就会出现这种问题
示例2:使用两个连接条件 所以在连接两个表的时候就不能仅仅看paytime这一个字段,还要结合userid字段,略微调整一下SQL语句:
select uo.userid,uo.amount,ump.mp
from (select userid,min(paytime) as mp from user_order group by userid) as ump
join user_order as uo on ump.mp=uo.paytime and ump.userid=uo.userid order by userid;
示例3:使用where条件 同样的效果也可以使用where条件语句达到:
select uo.userid,uo.amount,ump.mp
from (select userid,min(paytime) as mp from user_order group by userid) as ump, user_order as uo
where ump.userid=uo.userid and ump.mp=uo.paytime order by userid;
8.分组求最大最小类问题
这里有一张学生成绩表,其中包含学生编号,课程编号,成绩;还有一张课程表,其中包含课程编号,课程名称。求每门课程编号,课程名称以及每门课程最高的成绩。
[思路讲解]
1.首先确定题干要求的查询结果
其中课程名称保存在课程表中,成绩保存在成绩表中。两表都有课程编号。所以需要使用多表连接。还需要找出每科最高分,所以需要把课程编号和每科最高分作为关联两表的筛选条件加上。
select 课程.课程编号, 课程.课程名称, 成绩.每科最高分
2.先查找出每门课程的最高分。——确定查询条件
SELECT 课程编号, MAX(成绩)
FROM 成绩
GROUP BY 课程编号;
3.连接两表。确定连接主键和筛选条件。我们在第2步确定了查询条件,所以在这一步加到两表连接的筛选条件中。
select b.课程编号, b.课程名称, a.成绩
from 成绩 a
join 课程 b
on a.课程编号=b.课程编号
where (a.课程编号,a.成绩) in
(select 课程编号,max(成绩) from 成绩 group by 课程编号);
4.考虑下有可能出现最高分重复的情况。所以在课程编号前加上去重函数
select DISTINCT b.课程编号, b.课程名称, a.成绩
from 成绩 a
join 课程 b
on a.课程编号=b.课程编号
where (a.课程编号,a.成绩) in
(select 课程编号,max(成绩) from 成绩 group by 课程编号);
184. 部门工资最高的员工
Employee 表包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id。
Department 表包含公司所有部门的信息。
编写一个 SQL 查询,找出每个部门工资最高的员工。例如,根据上述给定的表格,Max 在 IT 部门有最高工资,Henry 在 Sales 部门有最高工资。
SELECT
Department.name AS 'Department',
Employee.name AS 'Employee',
Salary
FROM
Employee
JOIN
Department ON Employee.DepartmentId = Department.Id
WHERE
(Employee.DepartmentId , Salary) IN
( SELECT
DepartmentId, MAX(Salary)
FROM
Employee
GROUP BY DepartmentId
)
9.删除重复
现有一张同学的邮箱表,里面包含学生编号和邮箱两列,现要求删除相同邮箱的记录,且重复的邮箱只保留学生编号最小的那个。
2.学会转换思考问题的角度,运用我们学过的知识解决没有见过的问题。
前面学习过主键不相等的多表如何连接。这里我们可以使用自连接找出邮箱相等,学生编号不相等的记录。
3.确定连接主键。需要找到邮箱相同,所以a.邮箱 = b.邮箱。需要找出所有比最小的学生编号大的记录删掉。所以a.学生编号>b.学生编号。两个连接条件组合返回所有比最小学生编号大的学生的记录。
DELETE a
FROM 邮箱 a,
邮箱 b
WHERE
a.邮箱 = b.邮箱 AND a.学生编号 > b.学生编号
196.删除重复的电子邮箱
DELETE p1 FROM Person p1,
Person p2
WHERE
p1.Email = p2.Email AND p1.Id > p2.Id
11.订单取消率计算
262.行程和用户
有两张表,一张为订单表,一张为用户表。
订单 表中存所有出租车的行程信息。每段行程有唯一键 订单编号。乘客编号 和 司机编号 是 用户 表中 用户编号 的外键;意为司机和乘客都是用户,都保存在用户表中,通过角色这一字段列区分司机或是乘客。订单 表中的订单状态列反应订单状态,是已经完成,被司机取消亦或是被乘客取消。
用户 表存所有用户。每个用户有唯一键 乘客编号。被禁止 表示这个用户是否被禁止,角色 则是一个表示(‘乘客’, ‘司机’)的枚举类型。
写一段 SQL 语句查出 2013年10月1日 至 2013年10月3日 期间未被禁止用户的取消率。
[解题思路]
1.多表联结
统计未被禁止的用户取消订单率的前提是未被禁止乘客或者是未被禁止的司机,需要用到“用户表”里的”角色“和“被禁止”两个字段来判断。取消率需要用到“订单表”。所以涉及到两个表里的数据,就要用到在SQL面试题详解-多表如何查询这篇文章里讲过的多表联结。
那么,使用哪种联结呢?
统计值为取消率,所以使用“订单表”为主表,进行左联结。
select *
from 订单表
left join 用户表;
如何联结呢?
两个表的关系:订单表表的“乘客编号” 、 “司机编号” 和用户表的 “用户编号” 联结。所以联结条件是:
订单表.乘客编号 = 用户表.用户编号 or 订单表.司机编号 = 用户表.用户编号
基于上面的分析,多表联结查询sql语句如下:
select *
from 订单表
left join 用户表 u1 ON t.乘客编号 = u1.用户编号 AND u1.角色 = 'client' AND u1.被禁止='No'
left join 用户表 u2 ON t.司机编号 = u2.用户编号 and u2.角色 = 'driver' AND u2.被禁止='NO'
2.查询条件
我们看到1号订单乘客和司机都未被禁止,2号订单乘客被禁止。题目要求计算未被禁止用户的,所以需要增加筛选条件
where 用户表.被禁止 = ‘No’
代码汇总
select *
from 订单表 t
left join 用户表 u1 ON t.乘客编号 = u1.用户编号 AND u1.角色 = 'client' AND u1.被禁止='No'
left join 用户表 u2 ON t.司机编号 = u2.用户编号 and u2.角色 = 'driver' AND u2.被禁止='NO'
where u1.被禁止 = 'No'
and u2.被禁止 = 'No'
3.计算取消率
取消订单数 = sum(if(订单表.订单状态 in (‘cancelled_by_driver’,‘cancelled_by_client’),1,0))
订单总数 = count(*)计算取消率。
两者相除,订单取消率 = 取消订单数/订单总数。结合上一步得到的结果,就是未被禁止的用户的订单取消率。
SELECT t.Request_at Day,
round(sum(if(t.Status in('cancelled_by_driver','cancelled_by_client'),1,0))/count(*),2) `Cancellation Rate`
FROM Trips t
left join Users u1 ON t.Client_Id = u1.Users_Id AND u1.Role = 'client' AND u1.Banned='No'
left join Users u2 ON t.Driver_Id = u2.Users_Id and u2.Role = 'driver' AND u2.Banned='NO'
where
u1.Users_Id is not null
and u2.Users_Id is not null
4.题干要求在2013年10月1日 至 2013年10月3日 期间,每日的取消率。所以还需要添加筛选条件 t.Request_at between date(‘2013-10-1’) and date(‘2013-10-3’)。然后按照日期分组计算。
[代码]
SELECT t.Request_at Day,
round(sum(if(t.Status in('cancelled_by_driver','cancelled_by_client'),1,0))/count(*),2) `Cancellation Rate`
FROM Trips t
left join Users u1 ON t.Client_Id = u1.Users_Id AND u1.Role = 'client' AND u1.Banned='No'
left join Users u2 ON t.Driver_Id = u2.Users_Id and u2.Role = 'driver' AND u2.Banned='NO'
where
u1.Users_Id is not null
and u2.Users_Id is not null
and t.Request_at between date('2013-10-1') and date('2013-10-3')
group by t.Request_at;
17.行列转换问题
1179.重新格式化部门
有一张部门收入表。这表表有保存了三列信息,为部门编号,月份,收入。现要求编写一个 SQL 查询来重新格式化表,使得新的表中有一个部门 id 列和一些对应 每个月的收入(revenue)列。
2.如何实现表的行转列。
前面的文章中我们学习过case… when…,这里解释下:
CASE表达式会对最初的WHEN字句中的<判断表达式>进行判断开始执行。如果该表达式的真值为真(TRUE),那么就返回THEN字句中的表达式,CASE表达式到此为止。如果结果不为真,那么就跳转到下一句WHEN字句的判断之中。如果直到最后的WHEN字句为止返回结果都不为真,那么就会返回ELSE中的表达式,执行终止。
我们使用case…when…找出了每个月的收入,现在要将收入转换到列上,可以使用聚合函数,如sum,max,min等函数。
SELECT
部门编号,
sum(case 月份 when 'Jan' then 收入 else null end) as Jan,
sum(case 月份 when 'Feb' then 收入 else null end) as Feb,
...
FROM 部门收入表
– 拼多多笔试
use sqloa;
求第n高的数据
select student_id
FROM (SELECT student_id, Rank
RANK_NUMBR() OVER (PARTITION BY student_id order by grade DESC) as Rank
FROM Enrollments
ORDER BY Rank) as A
where A.Rank = 1;
SELECT user_id
FROM
(SELECT user_id,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY
unix_timestamp DESC) AS order_desc
FROM query_one
) tmp
WHERE order_desc = 1
ORDER BY user_id
LIMIT 5;
IN和EXISTS的区别:
in和exist的区别,哪个效率更好。你知道哪些优化方法。
区别:IN和EXISTS的区别:in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。
效率:如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in。
in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询,一直以来认为exists比in效率高的说法是不准确的。如果查询的两个表大小相当,那么用in和exists差别不大;如果两个表中一个较小一个较大,则子查询表大的用exists,子查询表小的用in。
in会使用你的子查询字段去到主表匹配你需要的行,而exists是根据匹配项去判断是或者否,然后根据是否决定结果,子查询的表大,用exists判断,效率就会高;而当子查询很小的时候,用in直接匹配你需要的值则更快。比如主表4万行,子查询里面有5条数据,那么exists会把4万行在子查询里面进行匹配,匹配上了就显示,匹配不上就不显示,所以需要判断4万次,而in则会在主表4万行里面去检索这5条记录,由于索引等等的存在,in的效率通常会更高,但是如果反过来,主表5条记录,子查询里面有4万行,exists只进行5次判断,而in会用4万个数据去匹配这5条记录,当然exists更快。
SQL优化方法:
我们在这里写出几条sql代码优化的建议:
对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
最左前缀匹配原则。mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配。所以要尽量把“=”条件放在前面,把这些条件放在最后。
尽量将or 转换为 union all
不使用索引:
sql select * from user where name=’a’ or age=’20’
使用索引:
sql select * from user where name=’a’ union all select * from user where age=’20’
当取出的数据超过全表数据的20%时,不会使用索引。
尽量避免使用is null或is not null。
除非确实需要去掉重复的行,否则尽量使用union all而不是union。因为union会自带distinct操作,代价很大 。
视图
视图(view)是一种虚拟存在的表,是一个逻辑表,本身并不包含数据。作为一个select语句保存在数据字典中的。
通过视图,可以展现基表的部分数据;视图数据来自定义视图的查询中使用的表,使用视图动态生成。
基表:用来创建视图的表叫做基表base table
[视图的优点]
简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现。
数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。
总而言之,使用视图的大部分情况是为了保障数据安全性,提高查询效率。
[语法]
视图的创建
sql create view <视图名称>[(column_list)] as select语句
使用show create view语句查看视图信息
sql show create view <视图名称>;
视图一旦创建完毕,就可以像一个普通表那样使用,视图主要用来查询
sql select * from view_name;
视图的更改
CREATE OR REPLACE VIEW语句修改视图
ALTER语句修改视图
DML操作更新视图