10)mysql高级SQL语句

视图(Views)
视图是可视化的表
在sql中,视图是基于sql语句的结果集的可视化表
视图包含行和列,像一个真实的表,数据来自1个或多个数据库表中的真实字段
可以向视图添加sql函数,where,join语句,也可以呈现数据
视图总是显示最新的数据,每当用户查询视图时,数据库引擎通过sql语句重建数据

创建视图语法
CREATE VIEW view_name 
    AS
    SELECT column_name(s)
    FROM table_name
    WHERE condition

示例
-- 创建视图
CREATE VIEW vm_course
AS
SELECT a.course_id,a.titl`vm_course`e,b.class_name,c.type_name,d.level_name
FROM imc_course a
JOIN imc_class b ON b.`class_id`=a.`class_id`
JOIN imc_type c ON c.type_id=a.type_id
JOIN imc_level d ON d.level_id=a.level_id;

-- 查询视图
SELECT * FROM vm_course;

-- 加过滤条件
SELECT * FROM vm_course WHERE course_id < 10;

撤销视图
DROP VIEW view_name

  • 公共表达式CTE(Common Table Expression)
  1. mysql8.0之后版本才可以使用,一般用来代替子查询,性能和可读性都优于子查询
  2. CTE生成1个命名临时表,并只在查询期间有效
  3. CTE临时表在一个查询中可以多次引用以及自引用
CTE基础语法
WITH [ RECURSIVE ]
cte-name [ (column_list) ]  AS  (
    query
)
[ , cte_name [ (column_list) ]  AS  (
    query
)]
SELECT * FROM cte_name;

RECURSIVE:  循环,表明这个表可以自引用
cte_name:  表名
column_list:  列定义
query:  query的结果就是临时表中的数据
可以同时定义多个公共表,每个表之间用逗号隔开
注意:query的出来的列数必须和 column_list 中的列相同,
如果省略column_list,将使用query的列作为列定义

示例
-- 最简单的公共表达式
WITH cte AS (
SELECT title,study_cnt,class_id
FROM imc_course
WHERE study_cnt>2000
)
SELECT * FROM cte
UNION ALL
SELECT * FROM cte  -- 子查询是不可以多次引用的
ORDER BY title

输出
title                   study_cnt  class_id  
----------------------  ---------  ----------
MySQL课程-04045                6646           2
MySQL课程-04045                6646           2
MySQL课程-04097                5245           5
MySQL课程-04097                5245           5


-- cte生成递归序列
WITH RECURSIVE cte_name AS (
SELECT 1 AS n
UNION
SELECT 1+n FROM cte_name WHERE n < 5
)
SELECT *
FROM cte_name

输出
     n  
--------
       1
       2
       3
       4
       5


-- 递归查询出课程的评论信息,例如课程查课程59的评论
WITH RECURSIVE replay(quest_id,quest_title,user_id,replyid,path) -- 参数列表
AS (
SELECT quest_id,quest_title,user_id,replyid,CAST(quest_id AS CHAR(200)) AS path
FROM imc_question
WHERE course_id=59 AND replyid=0 -- replyid==0说明该评论是根评论
UNION ALL
SELECT a.quest_id,a.quest_title,a.user_id,a.replyid,CONCAT(b.path,'>>',a.quest_id) AS path
FROM imc_question a
-- 递归查询出对根评论的回复,a表中的记录是b表的回复
-- 如要求2320得2257的path,故只会先求2257再求2320
JOIN replay b ON a.replyid=b.quest_id 
)
SELECT *
FROM replay

输出
quest_id  quest_title                                                                               user_id  replyid  path              
--------  ----------------------------------------------------------------------------------------  -------  -------  ------------------
1379  用户:2214关于 MySQL课程-98454第 10章第 2节的问答                                                          2214        0  1379              
1393  用户:2214关于 MySQL课程-98454第 9章第 2节的问答                                                           2214        0  1393              
1471  用户:324关于 MySQL课程-98454第 4章第 2节的问答                                                             324        0  1471              
1585  用户:3002关于 MySQL课程-98454第 14章第 2节的问答                                                          3002        0  1585              
1591  用户:1083关于 MySQL课程-98454第 6章第 8节的问答                                                           1083        0  1591              
1760  用户:1083关于 MySQL课程-98454第 3章第 2节的问答                                                           1083        0  1760              
1794  用户:4166关于 MySQL课程-98454第 12章第 11节的评论                                                         4166        0  1794              
1827  用户:324关于 MySQL课程-98454第 1章第 4节的问答                                                             324        0  1827              
1866  用户:3002关于 MySQL课程-98454第 15章第 1节的评论                                                          3002        0  1866              
1888  用户:324关于 MySQL课程-98454第 11章第 6节的问答                                                            324        0  1888              
2246  用户:2991对于 用户:324关于 MySQL课程-98454第 4章第 2节的问答的回复                                         2991 1471  1471>>2246        
2257  用户:2832对于 用户:2214关于 MySQL课程-98454第 10章第 2节的问答的回复                                       2832 1379  1379>>2257      
2320  用户:2476对于 用户:2832对于 用户:2214关于 MySQL课程-98454第 10章第                                        2476 2257  1379>>2257>>2320   

  • 窗口函数
    窗口函数是mysql8.0之后新增的功能,常用来对数据进行分组排序,比如成绩排名,各个类别的排名等等
窗口函数
function_name( [exp] )
OVER(
      [ PARTITION BY exp [, ...] ]
      [ ORDER BY exp [ ASC | DESC ] [, ...] ]
)

PARTITION BY : 对结果进行分组
ORDER BY     : 对分组后的结果进行编号,升序或降序

可以作为窗口函数的函数

  1. 聚合函数 : 聚合函数都可以作为窗口函数使用,如count(),avg(),min(),sum()等等
  2. ROW_NUMBER() : 返回窗口函数分区内数据的行号
  3. RANK() : 类似row_number,只是对相同的数据会产生重复的行号,之后的数据行号会产生间隔
  4. DENSE_RANK() : 类似rank,区别在于组内数据重复时,行号会重复,但后续的行号不会产生间隔
示例

'row_number,rank,dense_rank之间的区别'
WITH test(study_name,class_name,score) AS (
SELECT 'sqlercn','mysql',95
UNION ALL
SELECT 'tom','mysql',99
UNION ALL
SELECT 'jerry','mysql',98
UNION ALL
SELECT 'gavin','mysql',98
UNION ALL
SELECT 'sqlercn','postgresql',99
UNION ALL
SELECT 'jerry','postgresql',98
)
SELECT study_name,class_name,score
    ,ROW_NUMBER() OVER(PARTITION BY class_name ORDER BY score DESC) AS rw
    ,RANK() OVER(PARTITION BY class_name ORDER BY score DESC) AS rk
    ,DENSE_RANK() OVER(PARTITION BY class_name ORDER BY score DESC) AS drk
FROM test
ORDER BY class_name,rw

输出
study_name  class_name   score      rw      rk     drk  
----------  ----------  ------  ------  ------  --------
tom         mysql           99       1       1         1
jerry       mysql           98       2       2         2
gavin       mysql           98       3       2         2
sqlercn     mysql           95       4       4         3
sqlercn     postgresql      99       1       1         1
jerry       postgresql      98       2       2         2


'按学习人数对课程进行排名,
并列出每类课程学习人数排名前3的课程名称,学习人数以及名次'
WITH tmp AS (
SELECT class_name,title,score
    ,RANK()OVER(PARTITION BY class_name ORDER BY score DESC) AS cnt
FROM imc_course a
JOIN imc_class b ON b.class_id=a.class_id
)
SELECT * 
FROM tmp WHERE cnt<=3

输出
class_name       title                   score      cnt  
---------------  ----------------------  ------  --------
Docker           MySQL课程-57732           9.8            1
Docker           SQLServer课程-90092       9.8            1
Docker           PostgreSQL课程-27822      9.7            3
HadoopDock       SQLServer课程-52859       9.8            1
HadoopDock       PostgreSQL课程-71352      9.8            1
HadoopDock       PostgreSQL课程-00924      9.4            3
Hbase            MySQL课程-69546           9.9            1
Hbase            PostgreSQL课程-90898      9.9            1
Hbase            PostgreSQL课程-87282      9.8            3



'每门课程的学习人数占本类课程总学习人数的百分比'
WITH tmp AS (
SELECT class_name,title,study_cnt
    ,SUM(study_cnt) OVER(PARTITION BY class_name) AS class_total
FROM imc_course a
JOIN imc_class b ON b.class_id=a.class_id
)
SELECT class_name,title,CONCAT(study_cnt/class_total*100,'%')
FROM tmp
ORDER BY class_name

输出
class_name       title                   CONCAT(study_cnt/class_total*100,'%')  
---------------  ----------------------  ---------------------------------------
Docker           SQLServer课程-90092       19.6756%                               
Docker           PostgreSQL课程-85484      8.9576%                                
Docker           PostgreSQL课程-33460      27.6694%                               
Docker           SQLServer课程-41163       18.0422%                               
Docker           PostgreSQL课程-55484      1.5901%                                
Docker           SQLServer课程-60895       13.2316%                               
Docker           PostgreSQL课程-27822      0.5541%                                
Docker           MySQL课程-57732           10.2793%                               
HadoopDock       PostgreSQL课程-00924      17.5546%                               
HadoopDock       SQLServer课程-63911       6.8858%                                
HadoopDock       SQLServer课程-52859       16.1480%                               
HadoopDock       SQLServer课程-06325       1.3606%                                
HadoopDock       PostgreSQL课程-71352      28.0395%                               
HadoopDock       SQLServer课程-09426       30.0115%  

你可能感兴趣的:(10)mysql高级SQL语句)