MySQL 学习笔记 4:视图

news2025/1/4 15:47:36

MySQL 学习笔记 4:视图

image-20230710222532579

图源:ubiq.co

简单的说,视图就是“固化的SQL查询”。

这里看一个简单示例,我们有一个表,保存学生信息:

mysql> select * from student limit 10;
+-----+---------------+-----------+----------+
| id  | average_score | level     | name     |
+-----+---------------+-----------+----------+
| 573 |            27 | FRESH_MAN | Tom      |
| 574 |            76 | JUNIOR    | Icexmoon |
| 575 |             2 | JUNIOR    | BrusLee  |
| 576 |            56 | SOPHOMORE | Harry    |
| 577 |            44 | JUNIOR    | JackChen |
| 578 |            96 | JUNIOR    | Jimmy    |
| 579 |            73 | JUNIOR    | LiLei    |
| 580 |             4 | SENIOR    | XiaoMing |
| 581 |            21 | SOPHOMORE | Adam     |
| 582 |            40 | JUNIOR    | Alex     |
+-----+---------------+-----------+----------+

level字段表示年级,如果我们需要查询大一的学生:

mysql> select * from student where level='FRESH_MAN';
+-----+---------------+-----------+--------+
| id  | average_score | level     | name   |
+-----+---------------+-----------+--------+
| 573 |            27 | FRESH_MAN | Tom    |
| 586 |            61 | FRESH_MAN | Blake  |
| 591 |             6 | FRESH_MAN | Bruce  |
| 599 |            90 | FRESH_MAN | Xiaoli |
+-----+---------------+-----------+--------+

假设我们还需要统计大一学生的总平均分:

mysql> select sum(average_score)/count(id) as sum_average_score, sum(average_score) as total_average_score from student where level='FRESH_MAN';
+-------------------+---------------------+
| sum_average_score | total_average_score |
+-------------------+---------------------+
|           46.0000 |                 184 |
+-------------------+---------------------+

如果要频繁编写类似的查询语句,查询某某年级的学生的总平均分就很麻烦。

我们可以换个思路,能否创建一个“固化的查询结果”,内容是每个年级的统计结果,这样我们的查询语句就很简单了,只要针对这个统计结果按照年级查询即可。

首先我们看怎么分组统计不同年级的均分:

mysql> select `level`,count(id) as num,sum(average_score) as total_score, sum(average_score)/count(id) as sum_average_score
    -> from student
    -> group by `level`;
+-----------+-----+-------------+-------------------+
| level     | num | total_score | sum_average_score |
+-----------+-----+-------------+-------------------+
| FRESH_MAN |   4 |         184 |           46.0000 |
| JUNIOR    |  11 |         526 |           47.8182 |
| SOPHOMORE |   6 |         328 |           54.6667 |
| SENIOR    |   6 |         190 |           31.6667 |
+-----------+-----+-------------+-------------------+

创建视图

用 SQLyog 创建视图会出现类似下面的模版 SQL:

CREATE
    /*[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]
    [DEFINER = { user | CURRENT_USER }]
    [SQL SECURITY { DEFINER | INVOKER }]*/
    VIEW `jpa`.`student_stat_view` 
    AS
(SELECT * FROM ...);

student_stat_view是视图名称,视图名称必须在库中唯一(包括表名)。

我们只需要在AS之后添加SELECT语句即可完成视图创建语句:

CREATE
    VIEW `jpa`.`student_stat_view` 
    AS
SELECT `level`,COUNT(id) AS num,SUM(average_score) AS total_score, SUM(average_score)/COUNT(id) AS sum_average_score
FROM student
GROUP BY `level`;

查询视图

视图创建好后可以在 SQLyog 中看到,也可以使用以下命令查询:

show table status where comment='view';

要查看视图创建时的 SQL 语句:

show create view student_stat_view;

我们可以像查询普通表那样查询视图:

mysql> select * from student_stat_view;
+-----------+-----+-------------+-------------------+
| level     | num | total_score | sum_average_score |
+-----------+-----+-------------+-------------------+
| FRESH_MAN |   4 |         184 |           46.0000 |
| JUNIOR    |  11 |         526 |           47.8182 |
| SOPHOMORE |   6 |         328 |           54.6667 |
| SENIOR    |   6 |         190 |           31.6667 |
+-----------+-----+-------------+-------------------+

这样就很容易查询出我们需要年级的均分情况:

mysql> select * from student_stat_view where level='FRESH_MAN';
+-----------+-----+-------------+-------------------+
| level     | num | total_score | sum_average_score |
+-----------+-----+-------------+-------------------+
| FRESH_MAN |   4 |         184 |           46.0000 |
+-----------+-----+-------------+-------------------+

如果不使用视图,我们可能需要这么查询:

select `level`,count(id) as num,sum(average_score) as total_score, sum(average_score)/count(id) as sum_average_score
from student
group by `level` having `level`='FRESH_MAN'

视图的优缺点

可以从上面这个示例中看出,视图具有以下优点:

  • 简化 SQL 查询。
  • 让查询更直观。

视图也有缺点,视图本身并不保存数据,视图的数据都来自查询关联的基本表,视图本身只是一条查询 SQL。所以每次查询视图意味着执行了一条视图相关的 SQL,如果创建大量视图,且包含视图关联视图、视图嵌套视图、视图关联表等复杂查询语句,就可能造成性能问题。

简化多表联查

上面的示例演示了如何用视图简化聚合数据查询,视图还常用于简化多表联查。

假设我们有以下表:

mysql> select * from school;
+----+------------------+
| id | name             |
+----+------------------+
|  2 | 布斯巴顿魔法学校 |
|  1 | 霍格沃茨魔法学校 |
+----+------------------+

mysql> select * from student;
+----+----------+-----------+
| id | name     | school_id |
+----+----------+-----------+
|  1 | Harry    |         1 |
|  2 | icexmoon |         1 |
|  3 | JackChen |         2 |
+----+----------+-----------+

mysql> select * from email;
+----+----------+-----------+------------+
| id | account  | domain    | student_id |
+----+----------+-----------+------------+
|  1 | harry    | qq.com    |          1 |
|  2 | harry    | gmail.com |          1 |
|  3 | icexmoon | qq.com    |          2 |
|  4 | 111      | tom.com   |          2 |
|  5 | 123      | gmail.com |          3 |
|  6 | jack     | qq.com    |          3 |
+----+----------+-----------+------------+

假设我们需要查询使用了某种邮箱的学校,可能需要这么查询:

mysql> SELECT DISTINCT sc.id,sc.name FROM
    -> school AS sc
    -> LEFT JOIN student AS s
    -> ON s.school_id=sc.id
    -> LEFT JOIN email AS e
    -> ON e.student_id=s.id
    -> WHERE e.domain='gmail.com';
+----+------------------+
| id | name             |
+----+------------------+
|  1 | 霍格沃茨魔法学校 |
|  2 | 布斯巴顿魔法学校 |
+----+------------------+

不要问为什么会有这么古怪的要求…

可以用视图简化这个过程,我们可以创建一个表示学校和电子邮件的视图:

CREATE
    VIEW `jpa`.`school_email_view` 
    AS
SELECT sc.id AS school_id,sc.name AS school_name,e.id AS email_id, e.account AS email_account, e.domain AS email_domain FROM
school AS sc
LEFT JOIN student AS s
ON s.school_id=sc.id
LEFT JOIN email AS e
ON e.student_id=s.id;

这个视图直接体现了学校和学校学生拥有的电邮地址之间的关系:

mysql> select * from school_email_view;
+-----------+------------------+----------+---------------+--------------+
| school_id | school_name      | email_id | email_account | email_domain |
+-----------+------------------+----------+---------------+--------------+
|         2 | 布斯巴顿魔法学校 |        6 | jack          | qq.com       |
|         2 | 布斯巴顿魔法学校 |        5 | 123           | gmail.com    |
|         1 | 霍格沃茨魔法学校 |        2 | harry         | gmail.com    |
|         1 | 霍格沃茨魔法学校 |        1 | harry         | qq.com       |
|         1 | 霍格沃茨魔法学校 |        4 | 111           | tom.com      |
|         1 | 霍格沃茨魔法学校 |        3 | icexmoon      | qq.com       |
+-----------+------------------+----------+---------------+--------------+

利用视图可以很容易实现之前的查询:

mysql> select distinct school_id,school_name from school_email_view where email_domain='gmail.com';
+-----------+------------------+
| school_id | school_name      |
+-----------+------------------+
|         1 | 霍格沃茨魔法学校 |
|         2 | 布斯巴顿魔法学校 |
+-----------+------------------+

这样做还有个好处,我们可以无需理解三张表的联结关系,只需要按照需求查询视图即可。

简化字段计算

视图的另一个常见用途是对字段进行重新计算和处理,比如在上边的email表中,电子邮件帐号和网站是单独存放的字段,如果我们想要获取类似123@gmail.com这样的电邮地址,就需要在查询语句中字符串拼接,或者在代码端处理。

完全可以用视图简化这个过程:

CREATE
    VIEW `jpa`.`email_address_view` 
    AS
select id as email_id,concat(account,'@',domain) as email_address
from email
order by id;

查询视图:

mysql> select * from email_address_view;
+----------+-----------------+
| email_id | email_address   |
+----------+-----------------+
|        1 | harry@qq.com    |
|        2 | harry@gmail.com |
|        3 | icexmoon@qq.com |
|        4 | 111@tom.com     |
|        5 | 123@gmail.com   |
|        6 | jack@qq.com     |
+----------+-----------------+

相比维护一个冗余字段存储完整电邮地址,这样做的好处在于如果有帐号或者domain修改,email_address也会改变,无需我们重新维护。但这样是有代价的,是牺牲性能带来的。所以这是个取舍的问题,如果电子邮件改变的不频繁,并且需要我们进行性能优化,我们就可以考虑使用冗余字段存储,并且为添加和更新语句创建触发器,来解决维护冗余字段的问题。

视图和表联查

视图可以和表或其它视图联结查询:

mysql> select e.*,ev.`email_address`
    -> from email as e
    -> left join email_address_view as ev
    -> on e.id=ev.`email_id`;
+----+----------+-----------+------------+-----------------+
| id | account  | domain    | student_id | email_address   |
+----+----------+-----------+------------+-----------------+
|  1 | harry    | qq.com    |          1 | harry@qq.com    |
|  2 | harry    | gmail.com |          1 | harry@gmail.com |
|  3 | icexmoon | qq.com    |          2 | icexmoon@qq.com |
|  4 | 111      | tom.com   |          2 | 111@tom.com     |
|  5 | 123      | gmail.com |          3 | 123@gmail.com   |
|  6 | jack     | qq.com    |          3 | jack@qq.com     |
+----+----------+-----------+------------+-----------------+

视图的限制

视图也存在一些限制,比如视图不能使用索引

这很容易理解,视图本身并不存储内容,只是一条查询语句。而索引是创建在列上的,并且会创建一个B+树结构的存储数据。

修改 & 删除

用 SQLyog 修改视图会出现类似下面的模版:

DELIMITER $$

ALTER ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `school_email_view` AS 
select
  `sc`.`id`     AS `school_id`,
  `sc`.`name`   AS `school_name`,
  `e`.`id`      AS `email_id`,
  `e`.`account` AS `email_account`,
  `e`.`domain`  AS `email_domain`
from ((`school` `sc`
    left join `student` `s`
      on ((`s`.`school_id` = `sc`.`id`)))
   left join `email` `e`
     on ((`e`.`student_id` = `s`.`id`)))$$

DELIMITER ;

所以可以使用ALTER ... VIEW ... AS语句修改视图。

此外也可以先删除视图:

drop view school_email_view;

再重新创建。

The End,谢谢阅读。

参考资料

  • 《MySQL 必知必会》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/747865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

利用电价运行策略研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

外观模式:简化复杂系统的访问接口

外观模式是一种结构型设计模式,它提供了一个统一的接口,用于访问复杂系统中的一组接口。本文将深入探讨外观模式的原理、结构和使用方法,并通过详细的 Java 示例代码来说明。 1. 外观模式的定义 外观模式是一种通过提供一个简化的接口&…

LoggerFactory is not a Logback LoggerContext but Logback is on the classpath

springboot项目报错如下: 这个错误是由于在你的Java代码中使用了Logback日志库,但是同时又存在与Logback竞争的其他日志库(例如slf4j-simple)导致的冲突。 要解决这个问题,你可以尝试以下几个步骤: 1. 检…

计算机网关原理、子网掩码原理(路由器、交换机)(网关:与以太网接口关联的路由)

文章目录 网关网关的历史网关的功能网关的原理相关疑问为什么用子网掩码与IP地址进行与运算来确定一个IP地址所属的子网?网关地址是谁定的,是配置路由的人随意定的吗?(配置人员定的)如何正确设置网关地址(路…

WPF 如何引入图标文件

文章目录 前言:WPF 引入图标什么是ttf字体阿里云矢量库下载WPF引用为什么文件路径是#iconfont而不是iconfont。前面为什么要带个#号? 前言: 我最近在研究WPF,吃饭嘛,桌面端实在是不想用Winform,太丑了。WP…

WebDAV之π-Disk派盘+Notability

Notability 支持WebDAV方式连接π-Disk派盘。 Notability是一款功能强大的数字笔记应用,适用于iOS和macOS。它提供了优秀的手写体验,支持手写、录音和多种标记。用户可以记录想法、思路、绘图和草图,进行注释和标记,实现高效的学习和创作。同时,Notability具有文本输入、…

16 Java获取随机数

使用new Random创建一个随机数对象,然后调用里面的nextInt方法,方法中传入一个数字n,则随机数的范围为[0,n)。代码如下: package demo;import java.util.Random;public class Demo10 {public static void main(String…

xilinx zc706 以太网性能测试(iperf)

一:概述 以太网流量测试是一种评估网络性能和容量的测试方法。它通过模拟实际网络环境中的数据流量,以确定网络在高负载情况下的表现。 在以太网流量测试中,可以使用各种工具和技术来生成和控制数据流量。这些工具可以模拟不同类型的流量&a…

C#基础学习_集合中对象的动态排序

C#基础学习_集合中对象的动态排序 上一期我们了解了Icompare这种默认的排序方法,本次我们学习一下比较器ICompare的应用(可以替代Icompare这种默认的排序方法) 因为默认排序,只能有一种,使用起来可能会有局限性。 此时需要添加比较器: 根据需要,在需要实现动态排序的类…

生产管理“看得见“,这些车间工具必不可少!

工厂可视化是精益管理的重要组成部分,可视化的工厂管理可以从侧面提高员工精益生产的意识,那么工厂车间哪些方面可以做可视化管理呢? 目视化管理包括了三个内容: 1、管理规则的目视化:如通道线、安全警示、作业指导书…

掌握AI图像篡改检测工具,轻松识别图片造假

文章目录 一、前言1.1 背景与危害1.2会议探讨1.3 技术先行 二、亮点技术1:AI图像篡改检测技术2.1 传统方法Python实现步骤2.2 合合信息——PS纂改检测体验 三、亮点技术2:生成式图像鉴别3.1 生成式图像安全问题3.2 传统方法Python实现步骤3.2 合合信息—…

力扣 376. 摆动序列

题目来源:https://leetcode.cn/problems/wiggle-subsequence/description/ C题解1:使用flg标记第一个是增还是减,如果是平,则直接返回1;根据标记的flg,不断更新顶峰值和谷底值,直到最高或者最低…

LabVIEW使用数据引用减少内存

概览 NI LabVIEW 省略了 开发 软件时 需要 手动 管理 内存。LabVIEW 编译器 始终 会 分析 您 的 代码, 以 确定 如何 优 化 性能 并 减少 所需 的 内存 量。但是, 想要 更多 控制 内存 分配 的 高级 用户 可以 在 LabVIEW 2009 中创建 数据 引用。 内容…

记录一些杂七杂八的数据分析

1、数据库的独立性 --模式与内模式的映射 保证数据库物理结构的独立性 --模式与外模式的映射 保证数据库逻辑结构的独立性 2、常见的数据库 Oracle数据库,SQL Server数据库,MySQL数据库,PostgreSQL数据库。 3、数据分类 &…

day 52 子序列问题

不连续递增子序列的跟前0-i 个状态有关,连续递增的子序列只跟前一个状态有关 300. 最长递增子序列 dp[i]定义:以nums[i]结尾的最长递增子序长度递推公式:if (nums[i] > nums[j]) dp[i] max(dp[i], dp[j] 1); num[i] 之前各个位置,如果…

[静态库和动态库][VS2022]

静态库和动态库 前言:一、静态库二、动态库三、静态库和动态库的使用 前言: 我们写代码,可以分模块去写,最后可以协作,能整合起来; 可以吧代码的实现和声明分离。 比如:我的这篇博客C语言猜拳小…

【雕爷学编程】Arduino动手做(160)---HLK-V20离线语音模块

37款传感器与模块的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的&#x…

数据从发出到接收的细节介绍{封装与解封装}

系列文章目录 数通王国历险记(5) 目录 前言 一,数据封装的全过程 1.1,应用层的封装形式 1.2,传输层的封装形式 理解: 1.3,网络层的封装形式 理解: 1.4,数据链路层…

云计算——云计算关键技术

作者简介:一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭:低头赶路,敬事如仪 个人主页:网络豆的主页​​​​​ 目录 前言 一.云计算关键技术 1.虚拟化技术 2.分布式数据存储技术 (1&…

数据可视化之Tableau可视化||绘制标靶图

标靶图是一种用于评估、测试和优化计算机视觉算法的基准测试工具。它通常由多个具有不同特征的目标物体组成,如车辆、行人、交通信号灯等,同时包括各种不同的复杂场景,如城市街道、高速公路和人行道等。通过使用标靶图,研究人员可以检验算法的准确性、速度和适应性,同时拓…