SQL高级语句

主知识点八:窗口函数

新开窗口,不影响原数据的排序。且子句必须有order by。窗口结果返回到

且窗口函数必须写在select后面!

● 【排序窗口函数】

● rank()over()------1,1,3,4

● dense_rank()over()------1,1,2,3

● row_number()over()------1,2,3,4

【例题29】查询每一年S14000021选区中所有候选人所在的团体(party)和得票数(votes),并对每一年中的所有候选人根据选票数的高低赋予名次,选票数最高则为1,第二名则为2,后续以此类推,最后根据团体(party)和年份(yr)排序。

分析:

(1)查询团体(party)和得票数(votes)

(2)每一年的,S14000021选区的

(3)每一年中的所有候选人根据选票数的高低赋予名次------窗口函数rank()over(partition by yr order by votes desc)

(4)根据团体(party)和年份(yr)排序。

代码:

select yr,party,votes,rank()over(partition by yr order by votes desc)as posn

from ge

where constituency='S14000021'

order by party,yr

● 【偏移分析函数】

● lag(字段名,偏移量[,默认值])over()------当前行向上取值"偏移量"行

● lead(字段名,偏移量[,默认值])over()------当前行向下取值"偏移量"行

● 【例题30】查询法国和德国1月每天新增确诊人数,最后显示国家名、标准日期(2020-01-27)、当天截至时间累计确诊人数、昨天截至时间累计确诊人数、每天新增确诊人数,按照截至时间排序

分析:

(1)法国和德国1月每天新增确诊人数------where name in ('France','Germany') and month(whn) = 1

(2)最后显示国家名、标准日期(2020-01-27)、------date_format(whn,'%Y-%m-%d') date

当天截至时间累计确诊人数、------原表中的confirmed

昨天截至时间累计确诊人数、------,lag(confirmed,1)over(partition by name order by whn),当前行往上取1行,再取这一行的confirmed的值,

每天新增确诊人数

(3)按照截至时间排序

代码:

select

name

,date_format(whn,'%Y-%m-%d') date

,confirmed  当天截至时间累计确诊人数

,lag(confirmed,1)over(partition by name order by whn) 昨天截至时间累计确诊人数

,(confirmed - lag(confirmed,1)over(partition by name order by whn)) 每天新增确诊人数

from covid

where name in ('France','Germany') and month(whn) = 1

order by whn

结果:

● 【总结】

● 【排序窗口函数语法】

● rank()over([partition by 字段名] order by 字段名 asc|desc)

● dense_rank()over([partition by 字段名] order by 字段名 asc|desc)

● row_number()over([partition by 字段名] order by 字段名 asc|desc)

● 【偏移分析函数语法】

● lag(字段名,偏移量[,默认值])over([partition by 字段名] order by 字段名 asc|desc)

● lead(字段名,偏移量[,默认值])over([partition by 字段名] order by 字段名 asc|desc)

● 【题目】查询2017年选区为 'S14000024' 的所有候选人所在团体(party)和其选票数(votes)、还有候选人得票数在选区内对应的的排名,结果按团队party排序。

分析:

(1)查询候选人所在团体(party)和其选票数(votes)、

还有候选人得票数在选区内对应的的排名,

(2)2017年选区为 'S14000024' 的 ------where yr=2017 and constituency='S14000024'

(3)结果按团队party排序------order by party

代码:

select party,votes,rank()over(partition by constituency order by votes desc)as sort

from ge

where yr=2017 and constituency='S14000024'

order by party

● 【题目】查询截至时间为2020年4月20日的国家名,确诊人数,确诊人数排名,死亡人数,死亡人数排名,按照确诊人数降序排名。

分析:

(1)查询国家名,确诊人数,确诊人数排名,死亡人数,死亡人数排名,

(2)截至时间为2020年4月20日的

(3)按照确诊人数降序排名。

代码:

select name,confirmed,

rank()over(order by confirmed desc) cr,

deaths,rank()over(order by deaths desc) dr

from covid

where whn='2020-4-20'

order by confirmed desc

● 【题目】查询意大利每周新增确诊数(显示每周一的数值 weekday(whn) = 0),最后显示国家名,标准日期(2020-01-27),每周新增人数,按照截至时间排序。

分析:

(1)查询意大利每周新增确诊数------每周,两个相邻周一的数据相减就是这周的确诊数

(2)显示每周一的数值 weekday(whn) = 0,

(3)最后显示国家名,标准日期(2020-01-27),每周新增人数,

(4)按照截至时间排序。

代码:

select name,date_format(whn,'%Y-%m-%d') date,

(confirmed-lag(confirmed,1)over(partition by name order by whn))

from covid

where weekday(whn)=0 and name = 'Italy'

order by whn

主知识点九:表链接

表链接:把表连接在一起(3种方式)

(1)内连接:只两个表保留相同的

(2)左连接:合并后左边的表所有行都保留,若左边的表有空值则删除(即删除右边没有匹配上的)

(3)右连接:与左相反

● 【基础语法】

● 内连接

select 字段名

from 表名1 inner join 表名2 on 表名1.字段名 = 表名2.字段名

注意内连接inner可以省略,直接使用join默认为内连接

● 左连接

select 字段名

from 表名1 left join 表名2 on 表名1.字段名 = 表名2.字段名

● 右连接

select 字段名

from 表名1 right join 表名2 on 表名1.字段名 = 表名2.字段名

● 【例题31】查询有球员名叫Mario进球的队伍1(team1),队伍2(team2)及球员姓名.

分析:球员表+比赛表

● 两表连接键分别为id列和matchid列,连接方式为内连接

● from game join goal on game.id = goal.matchid

代码:

SELECT player,team1,team2

FROM goal inner join game

on game.id = goal.matchid  //不写on可能是完全连接

where player like '%Mario%'

● 【例题32】查询队伍1(team1)的教练是"Fernando Santos"的球队名称(teamname)、比赛日期(mdate)和赛事编号(id)

分析:

要查询的是球队名称(teamname)、比赛日期(mdate)和赛事编号(id)

限制是队伍1(team1),and教练是"Fernando Santos"

代码:

连接键game.team1=eteam.id

SELECT teamname,mdate,game.id                                        //有两个id要区分一下

FROM game join eteam

on game.team1=eteam.id                                                       //筛选队伍1中的教练

where coach='Fernando Santos'

● 【例题33】使用合适的连接显示所有教师及其所教授的科目名

分析:

是所有教师,则要左连接,否则有些老师会被清除,因为有些老师没有教课

代码:

select teacher.name,dept.name as dept

from teacher left join dept

on teacher.dept=dept.id

● 【题目1】查询至少出演过第1主角, 30次的演员名

代码:

SELECT name

FROM casting join actor

on casting.actorid=actor.id

where ord=1                                //至少出演过第1主角

group by name                               // 查询的是演员,结果要以演员name 进行分组(group by)

having count(movieid)>=30    

注意:group by字段名:规定依据哪个字段分组聚合,使用该子句是为了依据相同字段值分组后进行聚合运算,常和聚合函数联用

● 【题目2】查询在比赛前十分钟有进球记录的球员,他的队伍编号(teamid),教练(coach), 进球时间(gtime)

分析:

查询的是------队伍编号(teamid),教练(coach), 进球时间(gtime)

限制是------比赛前十分钟有进球记录的

代码:

SELECT teamid,coach,gtime

FROM eteam join goal

on eteam.id = goal.teamid    //不一定是表第一列作为连接

where gtime<=10

● 【题目3】查询每场比赛,每个球队的得分情况,按照以下格式显示。最后按照举办时间(mdate)、赛事编号(matchid)、队伍1(team1)和队伍2(team2)排序。

分析:

(1)得分表goal中出现的teamid就是得分队伍,即出现一次表示得分一次。

(2)每场比赛,每个球队------用group by按照场次、队伍分组

代码:

SELECT mdate,team1,sum(case when ga.team1=go.teamid then 1 else 0 end) score1,

team2,sum(case when ga.team2=go.teamid then 1 else 0 end) score2

FROM game ga

left join goal go

on ga.id = go.matchid

group by mdate,ga.team1,ga.team2

order by mdate,matchid,team1,score1,team2,score2

主知识点十:子查询

套娃逻辑

1、【where基于子查询条件筛选(比较运算符&in关键字)】

● 【例题34】查询出gdp高于欧洲每个国家的所有国家名,有一些国家gdp值可能为NULL,请排除这些国家。

分析:

(1)gdp高于欧洲每个国家,即gdp高于欧洲gdp最大的国家

先查出这个GDP最大的国家,然后再大于这个国家就好了

(2)请排除国家gdp值可能为NULL------is not null

代码:

select name

from world

where gdp is not null

and gdp>

( //返回最大gdp给上面的判断

select max(gdp) from world where continent = 'Europe'

)

2、【from基于子查询作为数据表】

● 【例题36】查询2017年所有在爱丁堡的选区当选议员所在选区(constituency)及其团队(party),已知爱丁堡选区编号为S14000021至S14000026,当选议员即各选区得票数最高的候选人。

分析:

(1)要查询:当选议员所在选区(constituency)及其团队(party)

(2)限制是:2017年,所有,在爱丁堡的(编号为S14000021至S14000026)

(3)当选议员:各选区得票数最高的候选人

代码1:

select yr,constituency,party,votes,

rank()over(partition by constituency order by votes desc) as pson

from ge

where yr = 2017

and constituency between 'S14000021' and 'S14000026'

以上代码可以找到2017年在爱丁堡选区,和票数的排名

再from从上面这个【表】中把pson=1 的筛选出来就好了:先将表另存为,再where 表.pson=1.

select constituency,party

from

(

select yr,constituency,party,votes,

rank()over(partition by constituency order by votes desc) as pson

from ge

where yr = 2017

and constituency between 'S14000021' and 'S14000026'

)data

where data.pson=1

● 【总结】

● 子查询本身是一个完整的查询,由括号包裹嵌套在主查询中

● 子查询最后返回查询出的结果给主查询

● 子查询可以在select,from,where,having子句(同where)中使用,但要注意不同子句能接受的子查询种类有差别

● 子查询可以多重嵌套(子查询可以作为主查询再嵌套子查询)

相关推荐
BergerLee23 分钟前
对不经常变动的数据集合添加Redis缓存
数据库·redis·缓存
程序员大金24 分钟前
基于SpringBoot+Vue+MySQL的装修公司管理系统
vue.js·spring boot·mysql
大神薯条老师31 分钟前
Python从入门到高手5.1节-Python简单数据类型
爬虫·python·深度学习·机器学习·数据分析
gorgor在码农37 分钟前
Mysql 索引底层数据结构和算法
数据结构·数据库·mysql
-seventy-42 分钟前
SQL语句 (MySQL)
sql·mysql
bug菌¹1 小时前
滚雪球学Oracle[6.2讲]:Data Guard与灾难恢复
数据库·oracle·data·灾难恢复·guard
一般路过糸.1 小时前
MySQL数据库——索引
数据库·mysql
Cengineering2 小时前
sqlalchemy 加速数据库操作
数据库
Cikiss2 小时前
微服务实战——平台属性
java·数据库·后端·微服务
小小不董2 小时前
《Linux从小白到高手》理论篇:深入理解Linux的网络管理
linux·运维·服务器·数据库·php·dba