SQL数据分析:

2022找工作是学历、能力和运气的超强结合体,遇到寒冬,大厂不招人,可能很多算法学生都得去找开发,测开
测开的话,你就得学数据库,sql,oracle,尤其sql要学,当然,像很多金融企业、安全机构啥的,他们必须要用oracle数据库
这oracle比sql安全,强大多了,所以你需要学习,最重要的,你要是考网络警察公务员,这玩意你不会就别去报名了,耽误时间!
oracle系列文章:
【1】Oracle数据库:啥是oracle数据库?你为啥要学oracle?
【2】Oracle数据库:oracle 11g安装教程,已安装好的oracle各个文件夹的作用,oracle用户权限怎么样
【3】Oracle数据库:oracle启动,oracle客户端工具plsql安装教程和使用方法
【4】Oracle数据库:创建表空间,创建新用户,给用户分配对象、角色和系统权限,登录新用户建表
【5】Oracle数据库:链接配置,包括sqlnet.ora里面的transnames.ora配置数据库标识符SID,listener暂时简单了解
【6】Oracle数据库:net configureation assistant工具配置监听listener,配置本地网络访问服务器上的数据库
【7】Oracle数据库:oracle字符类型、数字类型、创建表表名的命名规则
【8】Oracle数据库:约束条件:主键约束、唯一约束、检查约束、非空约束、外键约束、默认值填写
【9】Oracle数据库:表的关系:一对多,一对一,多对多,一一继承和修改的关系,表不是重点,重点是数据和约束关系
【10】Oracle数据库:sql语言结构,数据查询语言DQL,select * from table;算术,别名,连接,去重等操作
【11】Oracle数据库:约束行限制where语句,判断条件,比较条件,字符串日期格式,in,like,escape,null语句
【12】Oracle数据库:逻辑运算and,or,not和各种运算的优先级控制
【13】Oracle数据库:排序order by语句,select from where order by的执行先后顺序,各种样例
【14】Oracle数据库:oracle函数,单行函数,多行函数,upper,lower,initcap,字符串函数
【15】Oracle数据库:数字函数,日期函数,round,trunc,mod,months_between,add_months,next_day,last_day,sysdate
【16】Oracle数据库:oracle数据类型转换to_char()日期和数字转字符,to_number()字符转数字,to_date()字符转日期函数
【17】Oracle数据库:oracle函数嵌套,nvl函数,nvl2函数,nullif函数,coalesce合并函数
【18】Oracle数据库:条件表达式case when then else end,decode函数,oracle单行函数练习示例
【19】Oracle数据库:oracle多表查询,等值连接,非等值连接,自连接的sql语句和规则
【20】Oracle数据库:oracle外连接left/right/full outer join on,oracle扩展的左右外连接展示符号(+)
【21】Oracle数据库:自然连接natural join,using语句,注意避免写交叉连接
【22】Oracle数据库:oracle内连接inner join on,多表查询各种自链接、内连接、外连接的练习示例
【23】Oracle数据库:oracle组函数,聚合函数,多行函数,avg,sum,min,max,count,group by,having
【24】Oracle数据库:oracle嵌套分组函数(聚合函数),组函数的练习题,挺复杂的,用好decode函数,很有趣
【25】Oracle数据库:子查询、单行子查询,多行子查询,in,any,all语句,子查询的练习案例
————前面这些都是数据库查询语言的重要知识,一定要牢牢掌握和熟悉
后面的相对简单一点
【26】Oracle数据库:数据库操纵语言DML,插入insert into where,更新update where,删除delete where
【27】Oracle数据库:oracle事务处理语言TCL,commit,rollback,savepoint语句
【28】Oracle数据库:oracle数据定义语言DDL,查询表、序列、索引、视图、创建表,修改表的列alter,rename to,删除表数据truncate和表drop
【29】Oracle数据库:oracle用命令定义非空not null,unique唯一性,主键primary key,外键foreign key,check检查,启用enable,禁用disable约束
【30】Oracle数据库:创建和删除视图view,简单和复杂视图,内建视图,topN分析,oracle分页查询
【31】Oracle数据库:序列sequence的创建,查询,修改,删除,increment by,start with等关键字
【32】Oracle数据库:创建、修改、删除、使用同义词synonym和索引index
【33】Oracle数据库:创建用户user,设置密码,创建角色role,赋予权限grant,撤销权限revoke
【34】Oracle数据库:oracle执行计划性能代价cost,全表扫描速度慢,索引扫描速度快
【35】Oracle数据库:oracle数据表格dmp,sql,pde格式导入与导出,视图、序列、索引等对象的导出,oracle完结,后续开启mysql的学习


文章目录

  • SQL数据分析:
    • @[TOC](文章目录)
  • 数据分析师只需要会SQL查询语言,不需要其他的操作
  • sqlzoo数据说明
  • sql语法知识
  • 主知识点一:select from语句
    • distinct一定是在select后面,而不是字段的前面(理解的话)
    • 计算字段
  • 主知识点二:where
    • 模糊查询like
    • 多条件查询
  • order by排序
  • limit
  • 聚合函数&group by
  • having
  • 常见函数:数学类型
  • 常见函数:字符串函数
  • 常见函数:数据类型转换函数
  • 常见函数:日期转换函数
  • 常见函数:条件判断函数
  • 窗口函数
  • 表连接:内连接,左链接,右链接
  • 子查询:逻辑很重要
  • 云端数据库配置
  • 总结

sqlzoo
你要操作sql,所有的教程都在这个网站sqlzoo

https://sqlzoo.net/wiki/SQL_Tutorial

数据分析师只需要会SQL查询语言,不需要其他的操作

sqlzoo数据说明




novel表

covid表

ge表

等等,所有这些资料文件,请在上面文章【1】中下载
等等,所有这些资料文件,请在上面文章【1】中下载
等等,所有这些资料文件,请在上面文章【1】中下载

sql语法知识



总之,本文,我们要带你一步步学习sql查询语言的各种语法,骚操作,需要你写

你要操作sql,所有的教程都在这个网站sqlzoo

https://sqlzoo.net/wiki/SQL_Tutorial

很多语句它都给你写好了,你只需要执行看看结果
你也可以自己写写


你的把这个设置为mysql,英文版语言
否则数据有区别

你直接搁这文档里面写代码即可

然后修改,用英文输入法修改哦

可以得到不同的结果,反正按照你的所思所想展示

Checking a list The word IN allows us to check if an item is in a list. The example shows the name and population for the countries ‘Brazil’, ‘Russia’, ‘India’ and ‘China’.

Show the name and the population for ‘Sweden’, ‘Norway’ and ‘Denmark’.

in这个关键字,是非等值语句的范围查询
就是判断你是否有满足条件的东西在里面

SELECT name, population FROM worldWHERE name IN ('Brazil', 'Russia', 'India', 'China');

查查world表中那些名字in(–)里面的数据行
展示他们的name和population

美滋滋

Which countries are not too small and not too big? BETWEEN allows range checking (range specified is inclusive of boundary values). The example below shows countries with an area of 250,000-300,000 sq. km. Modify it to show the country and the area for countries with an area between 200,000 and 250,000.

between and
查询面积在a–b之间的国家

SELECT name, area FROM worldWHERE area BETWEEN 250000 AND 300000


你换一下呢

SELECT name, area FROM worldWHERE area BETWEEN 200000 AND 400000


看见这个网站了吗,给你一个样例,你可以任意改
select * from tableName where area between x and y

这些语句很简单,多练习就是了,没啥复杂的
这练习好了,考网警问题不大

剩下的东西,我就不复制过来了,你自己去那个网站敲代码,看结果,懂吗
自己动手,远比看,听,来得真实,来得舒服

主知识点一:select from语句

我主要带你玩几个核心的东西:
查询特定的几个字段

SELECT name, continent, population FROM world


很简单呗

查询所有字段,从world表里面

SELECT * FROM world

字段 as 别名
字段 别名

将这个字段改为这个别名

SELECT name 国家, continent 大洲, population 人口 FROM world

SELECT name as 国家, continent as 大洲, population as 人口 FROM world

这和oracle有点区别
oracle的汉语是必须要用""扩起来的
不过都是sql语言,大同小异

正经数据分析师,都不会写as,很拉跨,冗杂

distinct一定是在select后面,而不是字段的前面(理解的话)

数据去重
select distinct 字段名
from 表名

SELECT distinct continent FROM world


只看continent字段,但是不要重复

SELECT distinct name, continent FROM world


保证名字和大洲都不会重复
你不能这么写
名字不去重,而大洲去重

计算字段

select中的计算字段
select 字段名,计算字段
from 表名称
注意:计算字段中的算式所涉及的字段必须是表格中包含的,或者算式本身可以独立运算

算人均GDP=gdp/人口总数

SELECT name, gdp,population, gdp/population FROM world


Excel里面我们就玩过的哈哈哈哈
上面文章【1】【2】

看看去

一定要自己练习哦!

我熟练了
查查中国人均GDP

SELECT name, gdp,population, gdp/population FROM world where name='China'


人多肉少呗

where待会我们说,她是从表中出来的筛选条件
后面分组的筛选条件用having

主知识点二:where

标准的语法就是跟在from的后面

【标准语法】
select 字段名
from 表名
[where 表达式]

【语法解释】
where 表达式 限定查询行必须满足的条件
where核心子句是可选项,使用该子句是为了通过表达式筛选出符合查询条件的行数据

where 表达式 中运算符标准语法
select 字段名
from 表名
where 字段名 运算符 值

运算符

查询人口数至少2亿的国家名和人均gdp

SELECT name, gdp,population, gdp/population FROM world where population > 200000000


很简单的

!=等于
<>不等于
between and【a,b】之间
查询面积(area)在200000000和300000000之间的国家名和面积

SELECT name, gdp,population, gdp/population FROM world where population between 200000000 and 300000000


啥也没有叫null

它不是0,也不是数值
也不是别的东西

查询德国(Germany)的人口

SELECT name, gdp,population, gdp/population FROM world where name = 'Germany'

条件要等于啥,是字符串,需要单引号‘’

查询瑞典(Sweden)、挪威 (Norway) 和丹麦 (Denmark)的国家名和人口
in
你也可以and搞,麻烦

SELECT name, gdp,population, gdp/population FROM world where name in('Germany','Sweden', 'Norway', 'Denmark')

自己敲代码哦

模糊查询like


这和oracle一样
_一个任意字符
%任意字符,多个

模糊查询标准语法
select 字段名
from 表名
where 字段名 like ‘通配符+字符’

查询国家名中以C开头ia结尾的国家
中间是通配符
%

SELECT name, gdp,population, gdp/population FROM world where name like 'C%ia'


查询国家名中第二个字符为’t’的国家
第二个字符t
第一个字符就占位_
剩下的不管%

SELECT name, gdp,population, gdp/population FROM world where name like '_t%'


如果前后都有%
那就是含有t的国家

SELECT name, gdp,population, gdp/population FROM world where name like '%t%'


反正你记住_只能占一个位置

查询国家名中含有两个o且被两个字符隔开的国家名
俩o,而且还得把俩隔开

SELECT name, gdp,population, gdp/population FROM world where name like '%o__o%'

多条件查询

使用and或者or逻辑运算符对多个条件进行组合筛选想要的数据

and优先级高于or
最好加()

查询国家名中含有三个a且面积大于60万(600000)的国家及其面积

只要仨a就行

SELECT name, area FROM world where name like '%a%a%a%' and area >= 600000


查询国家名中含有三个a且面积大于60万(600000)的国家及其面积,或者人口大于13亿(1300000000)且面积大于500万(5000000)的国家及其面积

SELECT name, area FROM world where name like '%a%a%a%' and area >= 600000 or population >= 1300000000 and area >= 5000000


or优先级不高

最好我们加括号

SELECT name, area FROM world where (name like '%a%a%a%' and area >= 600000) or (population >= 1300000000 and area >= 5000000)

in 的效果

in在sql底层,它会自动转换你这个代码的
between and
最后转化为and



查询南美洲(south america)所有国家的名称以及它们以百万(1000000 )为单位的人口数量

SELECT name, population/1000000 peo_unit FROM world where name ='south africa'


查询1980年除诺贝尔化学奖和诺贝尔医学奖外其余奖项获奖者的所有信息
先看看Nobel都有哪些字段

select * from nobel;


化学奖
Chemistry
医学奖
Medicine
除开

年1980

SELECT * FROM nobel where yr=1980 and subject not in('Chemistry','Medicine')


查询既包含有所有元音字母(a,e,i,o,u),同时国家名中没有空格的国家,最后显示他们的名字
AEIOU
通配符%a%
还得没有空格,就是说,国家名字不能为% %
中间俩空格

SELECT name FROM world where name like '%a%' and
name like '%e%' and
name like '%i%' and
name like '%o%' and
name like '%u%' and
name not like '%  %'


同时包含aeiou,也不能有俩空格

查询1910年以前(不含1910)诺贝尔医学奖获得者和2004年及以后诺贝尔文学奖获得者的所有信息
前后都要
那就是或关系,满足就打印

SELECT winner FROM nobel where (yr < 1910 or yr >= 2004) and subject='Chemistry'

化学奖

order by排序

【标准语法】
select 字段名
from 表名
[where 表达式]
[order by 字段名 asc|desc]

查询姓名以Sir开头的获奖者(winner),获奖年份(yr)和科目(subject),查询结果按照年份从近到远排序,再按照姓名顺序升序排序

由于名字已经sir,不用排序了
用subject升序排序吧

SELECT winner,yr,subject from nobel where winner like 'Sir%' order by yr asc,subject asc


这是由远及近
其实年份应该降序

SELECT winner,yr,subject from nobel where winner like 'Sir%' order by yr desc,subject asc

查询1984年所有获奖者的姓名和奖项科目。
结果将诺贝尔化学奖和物理学奖排在最后
然后按照科目排序,再按照获奖者姓名排序

【注意,这是一个新知识点!】
你怎么让化学和物理刻意排后面呢???

如果order by 后面用in 单独点出来化学屋里,给他们赋值1
其余的赋值0
这样的话,0排前面,1排后面

完成放后面的任务

懂???

SELECT winner,yr,subject from nobel where yr = 1984 order by subject in('chemistry','physics'),subject,winner

这个写法确实第一次见,刺激


看,化学生物,排后面了

现有的内容,很难搞定这个题
这个新的用法,我们要好好学
这个新的用法,我们要好好学
这个新的用法,我们要好好学

那要是化学物理放前面呢?
那就是给他们赋值0
not in



很牛

limit

【标准语法】
select 字段名
from 表名
[where 表达式]
[order by 字段名 asc|desc]
[limit [位置偏移量,]行数]

【语法解释】
limit [位置偏移量,]行数 限制查询结果集显示的行数
limit子句是可选项,行数是子句中的必选参数,参数位置偏移量是可选参数

查询面积排名前三的国家
国家排名升序,然后分页展示
只能展示topk

select name from world order by name limit 3;

这种往往和order by配合

查询人口数第4到第7的国家和人口
总共4567要展示4行
从第4行开始展示的话
偏移先走3行,1,2,3这仨不展示,所谓的偏移量,懂吧

select name from world order by name limit 3,4;

先偏移3行,再展示4行

人口数,由高到低


从x+1行开始展示,拢共展示n行

OK

查询nobel表中第100行到120行的数据

select * from nobel limit 99,20;

聚合函数&group by

聚合
聚谁?
需要group by分组,分完咱们聚合,懂吧

否则就是聚合整个表

【标准语法】group by
select 字段名1
from 表名
[where 表达式]
[group by 字段名1]
[order by 字段名 asc|desc]
[limit [位置偏移量,]行数]

【语法解释】
group by 字段名 规定依据哪个字段分组聚合
group by核心子句是可选项,使用该子句是为了依据相同字段值分组后进行聚合运算,常和聚合函数联用

顺序:group by放在where之后,先执行,再排序,再select

查询非洲总人口数
限定非洲
求和是啥?,人口

咱们查一波
world表
name continent area population gdp capital tld flag
continent就是大洲名字
非洲Africa

select sum(population) afrPeo from world where continent='africa'


计算表格行数
整个表的行

select count(*) from world


你不能count某个字段
可能null忽略的

而且速度慢

count(*)速度快

你可以用group by配合分组完聚合函数

用group by 对大洲进行分组
查询每个大洲(continent)和大洲内的国家(name)数量

select continent,count(name) from world group by continent


from查全部数据,然后group by分组之后,才会根据不同的组,去计算count

查询2013至2015年每年****每个科目的获奖人数,结果按年份从大到小desc,人数从大到小desc排序

时间限制为2013–2015

年分组,然后才是科目分组

最后排序

select yr,subject,count(winner) from nobel where yr between 2013 and 2015 group by yr,subject order by yr desc, count(winner) desc

注意排序是先年,然后人数大小哦
count(winner)是人数个数


selcet最后运行
order by比select先执行
所以聚合函数先计算

你不选select,order by可以用聚合函数,也没问题的

select yr,subject from nobel where yr between 2013 and 2015 group by yr,subject order by yr desc, count(winner) desc


order by完事,我们不选count(winner)也没事的
反正select最后执行

计算Estonia, Latvia, Lithuania这几个国家的总人口数

select count(population) ​from world where name in('Estonia','Latvia','Lithuania'



应该是sum

select sum(population) ​from world where name in('Estonia','Latvia','Lithuania'


查询每个大洲和该大洲里人口数超过1千万的国家的数量
大洲分组
然后将人口数量超过1000w的国家捞出来
然后connt数量

select continent,count(name) from world where population>=10000000 group by continent

having

【标准语法】
select 字段名
from 表名
[where 表达式]
[group by 字段名]
[having 表达式]

[order by 字段名 asc|desc]
[limit [位置偏移量,]行数]

【语法解释】
having 表达式 限定分组聚合后的查询行必须满足的条件
having核心子句是可选项,使用该子句是为了对group by分组后的数据进行筛选

查询总人口数量至少为1亿(100000000)的大洲

你得按洲统计人口分组吧
还得展示洲总人口至少1亿的洲
条件是在聚合之后的筛选
不能用where,where是group by之前的筛选限定
懂????
所以筛选后再限定条件的话,用having

select continent,sum(population) from world group by continent having sum(population)>=100000000


先聚合再限定,就是要用having限定筛选,这里要学哦

查询总人口数至少为3亿的大洲和其平均gdp
其中只有gdp高于200亿且人口数大于6000万
或者gdp低于80亿且首都中含有三个a的国家的计入计算
最后按国家数从大到小排序,
只显示第一行

3亿那个必然是聚合之后having筛选
后面那些计入计算是聚合前筛选,where来限定
——这俩是关键
最后按国家数量,聚合count来排序
limit是显示,好说

select continent,avg(gdp) from world where (gdp>=20000000000 and population >= 6000000) or (gdp<=8000000000 and name like '%a%a%a%') group by continent having sum(population)>=300000000


然后排序和限定

select continent,avg(gdp) from world where (gdp>=20000000000 and population >= 6000000) or (gdp<=8000000000 and name like '%a%a%a%') group by continent having sum(population)>=300000000 order by sum(population)


国家数排序

select continent,avg(gdp) from world where (gdp>=20000000000 and population >= 6000000) or (gdp<=8000000000 and name like '%a%a%a%') group by continent having sum(population)>=300000000 order by count(name)


展示3行

select continent,avg(gdp) from world where (gdp>=20000000000 and population >= 6000000) or (gdp<=8000000000 and name like '%a%a%a%') group by continent having sum(population)>=300000000 order by count(name) limit 3

select continent,avg(gdp) from world where (gdp>=20000000000 and population >= 6000000) or (gdp<=8000000000 and name like '%a%a%a%') group by continent having sum(population)>=300000000 order by count(name) desc limit 3


稳了
反正搞清楚,聚合前筛选呢?还是聚合之后筛选
聚合前就是where,
聚合后就是having

标准语法
select 字段名
from 表名
[where 表达式]
[group by 字段名]
[having 表达式]
[order by 字段名 asc|desc]
[limit [位置偏移量,]行数]

运行原理
from–where–group by–having–order by–limit–select

select最后
from最前
聚合前筛选先
聚合之后筛选
然后排序,limit

顺序要搞清楚哦

查询人均gdp大于3000的大洲其人口数,仅gdp在200亿和300亿之间的国家计入计算
人均gdp
大洲,这么说,需要根据大洲分组,然后算人均GDP了
人口总数sum即可

计入计算的那些国家,是聚合前的条件筛选

select continent,sum(population) from world where gdp>=20000000000 and gdp<=30000000000 group by continent having sum(gdp)/sum(population)>=3000


很简单

人均,总gdp/总人口

好说

常见函数:数学类型

round()四舍五入
round(x,y)——四舍五入函数
round函数对x值进行四舍五入,精确到小数点后y位
y为负值时,保留小数点左边相应的位数为0,不进行四舍五入
例如:round(3.15,1)返回3.2,round(14.15,-1)返回10

认识一下dual伪表
操作不存在的表
为了from完整

SELECT 8*9 FROM dual

8*9也不需要哪里掏出来
所以dual伪表

SELECT round(0.111,2) FROM dual

常见函数:字符串函数

concat(s1,s2,…)——连接字符串函数
concat函数返回连接参数s1、s2等产生的字符串
任一参数为null时,则返回null
例如:concat(‘My’,’ ',‘SQL’)返回My SQL,concat(‘My’,null,‘SQL’)返回null

SELECT concat('a','bcd') FROM dual

来计算一波covid表中的治愈率
治愈人数/确诊人数*100%

select
confirmed
,deaths
,recovered
,recovered/confirmed
,concat(round((recovered/confirmed)*100,2),'%') 治愈率
from covid
where recovered/confirmed > 0.3

自己写一遍,把确诊,治愈的,都计算一下

SELECT recovered,confirmed,recovered/confirmed,concat(round(recovered/confirmed,2) * 100,'%') FROM covid where confirmed >0 and recovered > 0

replace(s,s1,s2)——替换函数
replace函数使用字符串s2代替s中所有的s1
例如:replace(‘MySQLMySQL’,‘SQL’,‘sql’)返回MysqlMysql

把a替换为kkk

SELECT replace('abcdefg','a','kkk') FROM dual

left(s,n)、right(s,n)&substring(s,n,len)——截取字符串一部分的函数
left函数返回字符串s最左边 n个字符
right函数返回字符串s最右边 n个字符
substring函数返回字符串s从第n个字符起取长度为len的子字符串,n也可以为负值,则从倒数第n个字符起取长度为len的子字符串,没有len值则取从第n个字符起到最后一位
例如:left(‘abcdefg’,3)返回abc,
right(‘abcdefg’,3)返回efg,
substring(‘abcdefg’,2,3)返回bcd,
substring(‘abcdefg’,-2,3)返回fg,
substring(‘abcdefg’,2)返回bcdefg
从哪开始截取,没有0位置哦

从start开始截取,n个

SELECT substring('abcdefg',2,2) FROM dual


左边截取2

SELECT left('abcdefg',2) FROM dual


右边截取2

SELECT right('abcdefg',2) FROM dual

常见函数:数据类型转换函数

cast(x as type)——转换数据类型的函数
cast函数将一个类型的x值转换为另一个类型的值
type参数可以填写char(n)、date、time、datetime、decimal等转换为对应的数据类型

常见函数:日期转换函数

year(date)、month(date)&day(date)——获取年月日的函数
date可以是年月日组成的日期,也可以是年月日时分秒组成的日期时间
year(date)返回日期格式中的年份
month(date)返回日期格式中的月份
day(date)返回年日期格式中的日份
例如:year(‘2021-08-03’)返回2021,month(‘2021-08-03’)返回8,day(‘2021-08-03’)返回3
——这玩意和Excel里面一样的
我们展示一下这个函数

select
whn 更新时间
,year(whn) 年
,month(whn) 月
,day(whn) 日
from covid
where recovered > 0

whn是covid表中的字段,咱们把这个字段,它是date数据类型,提取出年月日来

select whn,year(whn) "年",month(whn) "月",day(whn) "日" from covid where recovered > 0


在oracle里面是可以用||拼的哦

select whn,year(whn)||'年'||month(whn)||'月'||day(whn)||'日'  from covid where recovered > 0

这貌似不行

date_add(date,interval expr type)&date_sub(date,interval expr type)——对指定起始时间进行加减操作
date用来指定起始时间
date可以是年月日组成的日期,也可以是年月日时分秒组成的日期时间
expr用来指定从起始时间添加或减去的时间间隔
type指示expr被解释的方式,type可以可以是以下值
主要使用红框中的值

date_add函数对起始时间进行加操作,date_sub函数对起始时间进行减操作
例如:date_add(‘2021-08-03 23:59:59’,interval 1 second)返回2021-08-04 24:00:00,date_sub(‘2021-08-03 23:59:59’,interval 2 month)返回2021-06-03 23:59:59

select
whn 更新时间
,date_add(whn,interval 2 day) 加2天
from covid
where recovered > 0

interval就是间隔,这种格式你记住,跟oracle它不一样,你去看看我oracle里面讲的,跟着不同的
Oracle数据库:数字函数,日期函数,round,trunc,mod,months_between,add_months,next_day,last_day,sysdate

我自己手写一下mysql的这种格式

select whn, date_add(whn,interval 2 day) 加2天 from covid where recovered >0

这里要注意,这里的话,和oracle有区别哦
oracle的话,直接加,后面定格式

oracle的加2天是:
date+2
完事
加小时的话,是
date+天/24小时,很骚

datediff(date1,date2)——计算两个日期之间间隔的天数
datediff函数由date1-date2计算出间隔的时间,只有date的日期部分参与计算,时间不参与
例如:datediff(‘2021-06-08’,‘2021-06-01’)返回7,datediff(‘2021-06-08 23:59:59’,‘2021-06-01 21:00:00’)返回7,datediff(‘2021-06-01’,‘2021-06-08’)返回-7

select whn,datediff(whn,'2001-01-01') from covid

date_format(date,format)——将日期和时间格式化
date_format函数根据format指定的格式显示date值
可以换使用的格式有

例如:date_format(‘2018-06-01 16:23:12’,‘%b %d %Y %h:%i %p’)返回Jun 01 2018 04:23 PM,date_format(‘2018-06-01 16:23:12’,‘%Y/%d/%m’)返回2018/01/06
这玩意考就没意思了
没法记

常见函数:条件判断函数

if(expr,v1,v2)
如果表达式expr是true返回值v1,否则返回v2
例如:if(1<2,‘Y’,‘N’)返回Y,if(1>2,‘Y’,‘N’)返回N

case when
case expr when v1 then r1 [when v2 then r2] …[else rn] end
例如:case 2 when 1 then ‘one’ when 2 then ‘two’ else ‘more’ end 返回two
case后面的值为2,与第二条分支语句when后面的值相等相等,因此返回two

case when v1 then r1 [when v2 then r2]…[else rn] end
例如:case when 1<0 then ‘T’ else ‘F’ end返回F
1<0的结果为false,因此函数返回值为else后面的F

oracle里面是decode(expr,v1,r1,v2,r2)
很舒服

尝试一波:

select
recovered 累计治愈人数
,case when recovered = 1 then 'one' when recovered > 1 then 'more' else '0' end
from covid
where recovered > 0

自己动手写,当covid表中的recovered为1,展示1,大于1,展示more,否则展示0

查看全表

select * ​from covi


我来敲一波,这个格式不对?

select recovered, case recovered when 0 then 'zero' when 'one' then 1 else 'more' from covid

显然缺end哦
必须要确认的是,这个用法和oracle一样

0太多,咱们只需要展示1和上面的

select recovered, case recovered when 0 then 'zero' when 1 then 'one' else 'more' end from covid where recovered > 0

查询国家名称及其首都名称都以相同的字母开头的国家名及其首都,且不能包括国家名称和首都名称完全相同的情况
条件where限定国家名不等于首都名
我们需要截取第一个字符,判断相等不相等

SELECT name,capital FROM world where name != capital and left(name,1)=left(capital,1)


easy

查询首都和名称,其中首都需是国家名称的扩展
例如:答案中应该包括墨西哥城(Mexico City),因为它比墨西哥(Mexico)更长,而不应该将卢森堡(Luxembourg)包括在内,因为首都名与国家名相同

咱得知道国家名长度是多少

SELECT name,length(name)from world


那么就是说国家名长度x<首都名长度y

首都名从左截x个字符,必须等于国家名
懂吧
比如
墨西哥城(Mexico City)长度y=11
墨西哥(Mexico)长度x=6
起码y>x
还有(Mexico City)左边截取x=6个字符是Mexico,这样就满足扩展的条件了

SELECT name,capital from world where length(name)<length(capital) and left(capital,length(name))=name


好说
牛逼

但是还有更骚的做法
就是说国家名不等于首都

首都的模糊匹配是%name%

SELECT name,capital from world where name != capital and capital like concat(name,'%')

这种写法也很强

concat还是很牛的对吧


下面要玩高级语句了

窗口函数

【标准语法】
窗口函数over([partition by 字段名] [order by 字段名 asc|desc])

【语法讲解】
over()中两个子句为可选项,partition by指定分区依据,order by指定排序依据

【排序窗口函数】
rank()over()
dense_rank()over()
row_number()over()

【偏移分析函数】
lag(字段名,偏移量[,默认值])over()
lead(字段名,偏移量[,默认值])over()

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

假如,咱们不给他赋予名词
就字节按照团体和年份排序

看看ge表


constituency就是选区

SELECT yr,party,votes from ge where constituency='S14000021' order by party,yr

现在,我们要
并对每一年中的所有候选人根据选票数的高低赋予名次,选票数最高则为1,第二名则为2

咱们上面本身按照party和yr排序了
现在再这个基础上,我们又根据年份分区,然后根据votes排序,给每个party赋予排名序号

SELECT yr,party,votes,rank()over(partition by yr order by votes desc) rk from ge where constituency='S14000021' order by party,yryr   party   votes   rk
2015    Conservative    12465   3
2017    Conservative    21496   1
2019    Conservative    19451   2
2015    Labour  19295   2
2017    Labour  14346   3
2019    Labour  6855    3
2015    Liberal Democrats   1069    4
2017    Liberal Democrats   1112    4
2019    Liberal Democrats   4174    4
2015    SNP 23013   1
2017    SNP 16784   2
2019    SNP 24877   1
2015    UKIP    888 5

看见没

我们看看窗口函数的执行,它不受你where后面的order by的影响哦!!!
它就是回到最初最初那个where中形成的表来赋予rank

所以你看看我们打印的结果
那个rank,是窗口函数给的rank

这样,我们换个角度理解:如果我们没有按照party和yr排序,你看看rank会是啥

SELECT yr,party,votes,rank()over(partition by yr order by votes desc) rk from ge where constituency='S14000021'yr party   votes   rk
2015    SNP 23013   1
2015    Labour  19295   2
2015    Conservative    12465   3
2015    Liberal Democrats   1069    4
2015    UKIP    888 5
2017    Conservative    21496   1
2017    SNP 16784   2
2017    Labour  14346   3
2017    Liberal Democrats   1112    4
2019    SNP 24877   1
2019    Conservative    19451   2
2019    Labour  6855    3
2019    Liberal Democrats   4174    4

你瞅瞅,咱们窗口函数,是去最初where限定的这个表格中搞出来的表
做的rank赋值
懂吧???

然后至于,你后面再筛选啥的,无所谓的

相当于把原有数据表整为一个窗口,来重新分区,排序啥的。


首先呢,窗口函数只能用在select中

还有rank是有重复的阶跃,不连续
dense_rank是可以重复连续
row_number就是123456完全连续的

【偏移分析函数】
lag(字段名,偏移量[,默认值])over()
lead(字段名,偏移量[,默认值])over()

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

原表只有这几个

这个confirmed是累积的确诊数量哦!!!!!!当天截至时间累计确诊人数

昨天截至时间累计确诊人数、每天新增确诊人数
今天-昨天就是新增哦
昨天怎么拿,不就是按照日期排序,然后拿上一个行的数据

查询法国和德国,where就要限制好法德两国
月份1月,也时where来限定的
from covid where name in(‘Germony’,‘France’) and month(whn)=1

既然要分开展示,那要over搞窗口分区
over来搞窗口呗,国家分区,日期升序

lag(字段名,偏移量[,默认值])
lag,向上取n行

标准日期(2020-01-27)%y-%m-%d这是mysql的,但是oracle不一样,你要知道
date_fomat(whn,‘%y-%m-%d’)

最后展示这个月每天的情况,那需要按照日期有序展示,这不影响窗口函数
order by whn

当天截至时间累计确诊人数
confirmed
我们先看简单的

select name,date_format(whn,'%y-%m-%d'),confirmed from covid where name in('Germony','France') and month(whn)=1 order by whn

昨天截至时间累计确诊人数,即当天前一天的数据,用lag获取不同国家,前一天的数据
国家还得分区,日期也要顺序

select name,date_format(whn,'%y-%m-%d') 日期,confirmed 当天累计,lag(confirmed,1)over(partition by name order by whn) 昨日累计 from covid where name in('Germany','France') and month(whn)=1 order by whn

每天新增确诊人数=今天累计-昨日累计

select name,date_format(whn,'%y-%m-%d') 日期,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('Germany','France') and month(whn)=1 order by whn

name 日期  当天累计    昨日累计    当天新增
France  20-01-22    0
Germany 20-01-22    0
France  20-01-23    0   0   0
Germany 20-01-23    0   0   0
Germany 20-01-24    0   0   0
France  20-01-24    2   0   2
Germany 20-01-25    0   0   0
France  20-01-25    3   2   1
France  20-01-26    3   3   0
Germany 20-01-26    0   0   0
France  20-01-27    3   3   0
Germany 20-01-27    1   0   1
Germany 20-01-28    4   1   3
France  20-01-28    4   3   1
Germany 20-01-29    4   4   0
France  20-01-29    5   4   1
Germany 20-01-30    4   4   0
France  20-01-30    5   5   0
Germany 20-01-31    5   4   1
France  20-01-31    5   5   0
Germany 21-01-01    1762504 5   1762499
France  21-01-01    2697018 5   2697013
Germany 21-01-02    1773540 1762504 11036
France  21-01-02    2700484 2697018 3466
France  21-01-03    2712975 2700484 12491
Germany 21-01-03    1783896 1773540 10356
France  21-01-04    2717059 2712975 4084
Germany 21-01-04    1796216 1783896 12320
Germany 21-01-05    1814565 1796216 18349
France  21-01-05    2737892 2717059 20833
Germany 21-01-06    1841228 1814565 26663
France  21-01-06    2763078 2737892 25186
Germany 21-01-07    1886561 1841228 45333
France  21-01-07    2784845 2763078 21767
Germany 21-01-08    1905638 1886561 19077
France  21-01-08    2804705 2784845 19860
Germany 21-01-09    1928462 1905638 22824
France  21-01-09    2824882 2804705 20177
France  21-01-10    2840826 2824882 15944
Germany 21-01-10    1929410 1928462 948
France  21-01-11    2844642 2840826 3816
Germany 21-01-11    1941116 1929410 11706
Germany 21-01-12    1968326 1941116 27210
France  21-01-12    2864399 2844642 19757
Germany 21-01-13    1993892 1968326 25566
France  21-01-13    2888331 2864399 23932
Germany 21-01-14    2015235 1993892 21343
France  21-01-14    2909666 2888331 21335
France  21-01-15    2930983 2909666 21317
Germany 21-01-15    2023828 2015235 8593
Results truncated. Only the first 50 rows have been shown.

一步步搞清楚,其实就还好

over就是窗口函数,和后面的展示排序无关的
有了每日累计,就可以用lag拿到昨日累计
每日累计-昨日累计,就是今日新增

lag(confirmed,1)本行数据,上一行
lead(confirmed,1)本行数据,下一行

lag(confirmed,7)本行数据,上1周行
lead(confirmed,7)本行数据,下1周行

查询2017年选区为 ‘S14000024’ 的所有候选人所在团体(party)和其选票数(votes)、
还有候选人得票数在选区内对应的的排名
结果按团队party排序

选区为 ‘S14000024’ 的——where限定的

结果按团队party排序——where后面的order by搞定
不影响窗口函数的执行
还有候选人得票数在选区内对应的的排名——rank()给排序,over限定窗口,以votes排序

OK试试

select party,votes,rank()over(order by votes) rk from ge where constituency = 'S14000024' order by party

select party,votes,dense_rank()over(order by votes) rk from ge where constituency = 'S14000024' order by partyparty   votes   rk
Conservative    8161    8
Conservative    8626    9
Conservative    9428    10
Green   1357    3
Green   2090    6
Labour  19293   14
Labour  23745   15
Labour  26269   16
Liberal Democrats   1388    4
Liberal Democrats   1823    5
Liberal Democrats   3819    7
Scottish Socialist Party    197 1
SNP 10755   11
SNP 12650   12
SNP 16656   13
UKIP    601 2
select party,votes,row_number()over(order by votes) rk from ge where constituency = 'S14000024' order by party
party   votes   rk
Conservative    8161    8
Conservative    8626    9
Conservative    9428    10
Green   1357    3
Green   2090    6
Labour  19293   14
Labour  23745   15
Labour  26269   16
Liberal Democrats   1388    4
Liberal Democrats   1823    5
Liberal Democrats   3819    7
Scottish Socialist Party    197 1
SNP 10755   11
SNP 12650   12
SNP 16656   13
UKIP    601 2

注意他们的区别即可

2017年可能需要限定,你们自己搞吧

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

窗口函数是很高级的用法,不打扰别的计算

控制时间限制条件——时间需要直接判定年月日即可,它自动转换
这个确诊人数,死亡人数,就是累积的,而不是当天新增量哦
否则你搞复杂了
咱们独立运行窗口函数!!!!

确诊和死亡独立计算——这就是高级用法

结果是按照确诊人数降序

select name,rank()over(order by confirmed) rkC,rank()over(order by deaths) rkD from covid where whn='2020-04-20' order by confirmed desc

美国确诊最多

可以没用partition by

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

这个是要用lag计算的每周的

——weekday(whn) = 0每周周一,那么这个用where限定了,提示你新的函数weekday为0–6代表周一日
——按照截至时间排序,这个是where之后的排序,好说

你分区也只需要按照时间排序
不过你提取出来的数据都是周一的,
lag上一行,就是上周的数据哈哈哈哈哈哈
不是7哦,是lag上面1行

select name,date_format(whn,'%y-%m-%d'),confirmed-lag(confirmed,1)over(order by whn) everyWeek from covid where weekday(whn) = 0 and name='Italy' order by whn;


如果你一定要用lag7天
那么你捣鼓出来的数据,是要全部
但是你没法干到周一

select name,date_format(whn,'%y-%m-%d'),confirmed-lag(confirmed,7)over(order by whn) everyWeek from covid where name='Italy' having weekday(whn) = 0 order by whn;


这里就是窗口函数的经典之处了

如果不限定意大利的话,但是所有国家对可以展示

表连接:内连接,左链接,右链接


这种是笛卡尔乘积,内连接!没卵用

正常情况下,大家不用的

内连接是不保留null

left保留左边的所有数据
out保留右边的所有数据
full保留左右的所有数据

join就是不停地增加数据,左右匹配
oracle里面的话,这里作为了解,实际上用得多的是等值连接,不要inner join on这种玩意

这很复杂

查询有球员名叫Mario进球的队伍1(team1),队伍2(team2)及球员姓名

首先阅读并理解game、goal、eteam三表相关信息

这个id是对抗id,比赛的id
team1和team2的id有了

matchid是是对抗id,比赛的id
teamid是队伍id
gtime是不是进球个数?

这个队伍id对应的球队名字

查询有球员名叫Mario进球的队伍1(team1),队伍2(team2)及球员姓名

查询有球员名叫Mario,这个是限定条件——你需要goal表查名字
你得找到它所在的队伍team1,同时要找到它对抗的队伍team2
那就需要goal表,game表
你需要他们的队伍名字,需要eteam表
仨是内连接的关系
goal表,game表通过id和matchid内连接
goal和eteam通过matchid和id内连接

貌似这个,goal inner join eteam on goal.mathcid=eteam.id
是错误的链接,可能game和eteam才能挂接?
不对啊,

它这个都串了

select eteam.teamname,goal.player from goal inner join eteam on goal.teamid=eteam.id where goal.player like 'Mario%'

select game.team1,game.team2,goal.player from game inner join goal on game.id=goal.matchid where goal.player like 'Mario%'


两种方法都行

但是这仨不能同时相连……

查询队伍1(team1)的教练是“Fernando Santos”的球队名称(teamname)、比赛日期(mdate)和赛事编号(id)



我们只需要挂表game和eteam就行了吧

select eteam.teamname,game.mdate,game.id from game inner join eteam on game.team1=eteam.id where eteam.coach='Fernando Santos'

这次终于清楚了
这个eteam的id是team1或者team2
这俩是挂钩的,不是挂game的id,懂吧
game的id是挂goal的matchid的
OK


那其实内连接也就还挺简单的,并不复杂

使用合适的连接显示所有教师及其所教授的科目名
先看dept课程表和teacher表


要将dept表连接至teacher表才能显示教师名和科目名,连接键为dept.id = teacher.dept

这就好说了很简单,可以等值连接,也可以内连接
表格可以用别名的哦

select te.name,de.name from dept de inner join teacher te on de.id = te.dept

看清楚字段该连接谁
不是id对id,不同表的id不一样,懂吧


当老师都要展示的话,需要left join或者right
看你teacher表放左右边了
我这teach是右边
所以右外连接

select te.name,de.name from dept de right join teacher te on de.id = te.dept

select te.name,de.name from dept de left join teacher te on de.id = te.dept



full join只有oracle才有哦,哈哈哈哈哈,这事我oracle里面说过了
mysql里面没有这么高级的用法哦

查询至少出演过第1主角30次的演员名
涉及数据表:movie、casting、actor


casting 就是主演呗
这里面ord就是第ord主角


moviedid和movie表里面的id是挂接的
actorid和actor里面的id是挂接的
所以,演了超过30次1主角的

其实movie表咱们这里用不上
只需要actor表和和casting

你要演出过1主角的那些演员
先筛选ord=1的,然后在此基础上,按照演员名字分组
分组统计他们演过1角色的次数超过30次
相当于having来限定分组后的结果

这个很重要,鉴定条件是ord得1

select * from actor a join casting c on a.id=c.actorid where c.ord=1

在此基础上用演员名分组,分组后限定条件,having

select name from actor a join casting c on a.id=c.actorid where c.ord=1 group by a.name


看看他们是否超过30行

select name from actor a join casting c on a.id=c.actorid where c.ord=1 group by a.name having count(a.name)>=30


所以这些题的核心是算法逻辑
我要怎么才能知道它出演的次数,就count(name)
别学了半天还是学不会,生气

select a.name,count(a.name) from actor a join casting c on a.id=c.actorid where c.ord=1 group by a.namename    count(a.name)
Warren Beatty   9
Paul Hogan  4
Paul Hogan<br>    1
Jeanne Tripplehorn  1
Merle Oberon    4
Peter Schildt<br> 1
Charlize Theron 5
Joseph Gordon-Levitt    4
Adam Goldberg   1
Hume Cronyn 1
Steven Strait   2
Glenn Close 7
Barry Bostwick  2
Victoria Abril  3
Dudley Moore    4
Richard Attenborough    9
Julia Stiles    4
Charles Bronson 18
Rachel Leigh Cook   1
James Franco    4
Sergei Makovetsky   1
Henry Fonda 22
Bruce Willis    31
John Cena   1
Charles Herbert 1
Jennifer Garner 4
Jennifer Beals  2
James Cagney    29
John Cusack 19
Gérard Depardieu   15
Claire Trevor   4
Robert De Niro  29
Reidar Sørensen    1
William Daniels 1
Zac Efron   4
Robert Downey, Jr.  10
Kim Gordon  1
Lois Alexander<br>Curtis Benton<br>Wallace Clarke<   1
Kirk Douglas    17
Spencer Tracy   30
Keir Dullea 5
The Mothers of Invention    1
Roy Scheider    12
Myles Berkowitz<br>   1
William Hopper  1
Jim Sturgess    4
Sean Penn   14
Van Johnson 6
Steve Coogan    3
Edward Norton   4
Results truncated. Only the first 50 rows have been shown.

ord=1的,你看看如果名字分组,再统计个数,就能知道它们大概是多少
这时候,你在分组之后having筛选就可

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

涉及数据表:<game、game、eteam>



eteam是队伍的标识
和goal的teamid挂钩的
goal的matchid和game的id是挂钩的

查询在比赛前十分钟有进球记录的球员,他的队伍编号(teamid),教练(coach), 进球时间(gtime)
gtime就是进球时间时间呗
where筛选gtim<=10的
队伍编号,很好办
只需要goal表和eteam表

select * from goal g join eteam e on g.teamid = e.id where g.gtime<=10


前十分钟进球的数据就出来了
只展示题目要求的这些

select g.teamid,e.coach,g.gtime from goal g join eteam e on g.teamid = e.id where g.gtime<=10


这就很容易了

查询每场比赛,每个球队的得分情况,按照以下格式显示

最后按照举办时间(mdate)、赛事编号(matchid)、队伍1(team1)和队伍2(team2)排序

如果要区分team1和team2,这是需要咱们挂接game和goal表的
from goal go join game ga on go.matchid=ga.id

这个每场比赛,本身一个日期就是一个场次,也对应一个比赛id,它要作为分组条件
要区分team1和team2,他们在这场次里面球队的得分怎么算?这就要将teamid做为分组条件
但这里要注意:
相当于两个列team1和team2都格子生成了自己的一个数据表和goal表挂接了——这是join的内涵
team1_goal
team2_goal
由于俩队伍都是挂goal表,所以要讲这俩team都做一个分组
group by ga.mdate,ga.team1,ga.team2

goal里面只要有一个teamid,就算1分,至于这个team1还team2,你根据goal的teamid来判断,用case when语句搞定
select ga.mdate,ga.team1,sum(case go.teamid when ga.team1 then 1 else 0 end) score1,ga.team2,sum(case go.teamid when ga.team2 then 1 else 0 end) score2
第一个日期就是场次分组
在这种情况下,team1算一个表,将这个表里面的team1的个数累加就是分数
team2算一个表,将这个表里面的team2的个数累加就是分数

select ga.mdate,ga.team1,sum(case go.teamid when ga.team1 then 1 else 0 end) score1,ga.team2,sum(case go.teamid when ga.team2 then 1 else 0 end) score2 from goal go join game ga on go.matchid=ga.id group by ga.mdate,ga.team1,ga.team2mdate  team1   score1  team2   score2
8 June 2012 POL 1   GRE 1
8 June 2012 RUS 4   CZE 1
12 June 2012    GRE 1   CZE 2
12 June 2012    POL 1   RUS 1
16 June 2012    CZE 1   POL 0
16 June 2012    GRE 1   RUS 0
9 June 2012 NED 0   DEN 1
9 June 2012 GER 1   POR 0
13 June 2012    DEN 2   POR 3
13 June 2012    NED 1   GER 2
17 June 2012    POR 2   NED 1
17 June 2012    DEN 1   GER 2
10 June 2012    ESP 1   ITA 1
10 June 2012    IRL 1   CRO 3
14 June 2012    ITA 1   CRO 1
14 June 2012    ESP 4   IRL 0
18 June 2012    CRO 0   ESP 1
18 June 2012    ITA 2   IRL 0
11 June 2012    FRA 1   ENG 1
11 June 2012    UKR 2   SWE 1
15 June 2012    UKR 0   FRA 2
15 June 2012    SWE 2   ENG 3
19 June 2012    ENG 1   UKR 0
19 June 2012    SWE 2   FRA 0
21 June 2012    CZE 0   POR 1
22 June 2012    GER 4   GRE 2
23 June 2012    ESP 2   FRA 0
28 June 2012    GER 1   ITA 2
1 July 2012 ESP 4   ITA 0

子查询:逻辑很重要

一个套娃思想

子查询本身就是一段完整的查询语句,然后用括号英文括号**()**包裹嵌套在主查询语句中,子查询可以多层嵌套
最常用的子查询运用在from和where子句中

查询出gdp高于欧洲每个国家的所有国家名,有一些国家gdp值可能为NULL,请排除这些国家
首先,欧洲每个国家的gpd最大值是多少??这是需要弄出来的


七大洲

okay,我们找到欧洲国家gdp最高为

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

这个结果是一个值

主查询就好说了,直接查谁?比这个高,非欧洲的

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


括号里面就是子查询

查询跟阿尔及尼亚(Argentina)和澳大利亚(Australia)在同一大洲的所有国家名及其所属大洲, 并按照国家名进行排序

那这俩国家在哪个洲呢?看似结果可能是多行,这时候不能用等值了,就要用in来嵌套子查询哦

首先,看看这俩国家在哪个洲??

select continent from world where name in('Argentina','Australia')


结果有俩,我们要找其他的这些国家

相当于拿着这个子查询,作为限制条件,去查看哪些国家在这俩洲

select name,continent from world where continent in (select continent from world where name in('Argentina','Australia')) order by name


如果要排出刚刚那俩国家,可以排出就行

select name,continent from world where name not in('Argentina','Australia') and continent in (select continent from world where name in('Argentina','Australia')) order by namename  continent
Bolivia South America
Brazil  South America
Chile   South America
Colombia    South America
Ecuador South America
Fiji    Oceania
Guyana  South America
Kiribati    Oceania
Marshall Islands    Oceania
Micronesia, Federated States of Oceania
Nauru   Oceania
New Zealand Oceania
Palau   Oceania
Papua New Guinea    Oceania
Paraguay    South America
Peru    South America
Saint Vincent and the Grenadines    South America
Samoa   Oceania
Solomon Islands Oceania
Suriname    South America
Tonga   Oceania
Tuvalu  Oceania
Uruguay South America
Vanuatu Oceania
Venezuela   South America


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

用到了ge表

年,选区内各党派的得票数
得票数最高,那个排名为1的,展示出来,不就是最高的选票人

2017年,选区区间,where限定

最后展示啥呢,需要展示选区(constituency)及其团队(party)
还要展示这个排名第一的,票数最高的人

那首先需要干嘛?我们需要把这个党内排序最高的排序搞出来,排序序号123这些打印

select constituency,party,rank()over(partition by party order by votes desc) rk from ge where yr=2017 and constituency between 'S14000021' and 'S14000026'


这个事是跟where没关系的,是从原始的表中去搞的,所以你再having筛选也不行的,它在having之前运行懂吧?

所以怎么搞呢
要不
我们就把上面这个玩意当一个新表
我拿新表去限定rk=1,可不就是每个党派里面得票最高的候选人吗???

select constituency,party,lastname from (select constituency,party,lastname,rank()over(partition by party order by votes desc) rk from ge where yr=2017 and constituency between 'S14000021' and 'S14000026') r where r.rk=1

新表别忘了起名字哦
叫r
我们要r.rk=1的候选人

这波操作,确实很强,非常强,我们有窗口函数来梳理排名rk
然后当新表r
去筛选r.rk=1的那些人

from后面的子查询表,是必须要写别名的,否则别人没法找到你,懂吧?

查询在欧洲(Europe)人均gdp大于英国 (United Kingdom)的国家名
人均国内生产总值(人均GDP)=国内生产总值(GDP)/人口(populaiton)

用world表

首先我们看看:英国 (United Kingdom)的国家名
人均国内生产总值(人均GDP)=国内生产总值(GDP)/人口(populaiton)

select gdp/population ukAvgGDP from world where name='United Kingdom'


就一个数x
查询在欧洲(Europe)人均gdp大于x的国家

select name,gdp/population agvGDP from world where continent ='Europe' and gdp/population >(select gdp/population ukAvgGDP from world where name='United Kingdom')


查询人口数(population)超过加拿大(Canada)但是少于波兰(Poland)的国家,结果显示这些国家名(name)和人口数(population)

那么加拿大人数是?
波兰的人数是?



两者之间

select name, population from world where population between (select population from world where name='Canada') and (select population from world where name='Poland')

查询所有国家人口均≤25000000的大洲,及其国家名(name)和人口(population)
全部要小于等于这个数
那么每个大洲中的人口最大值是多少?里面最大值竟然大于这个数,就达标了

按照大洲分组,看看哪个max竟然<=这个数

也就是说这俩大洲的所有国家,他们的人口都小于这个

因此,这俩洲的国家和人数都可以展示了
查询所有国家人口均≤25000000的大洲,及其国家名(name)和人口(population)

select continent,name,population from world where continent in(select continent from world group by continent having max(population)<=25000000)


这很好说

先查大洲,再看别的信息

查找每个大陆(continent)中最大的国家(按区域area),显示该大洲(continent),国家名(name)和面积(area)
那就是说要按照area排序
排序之后有rk,我们只显示rk为1的
上面那个投票很相似,懂?

我们先将这个排序表弄出来

select continent,name,area,rank()over(partition by continent order by area desc) rk from world


拿这个表作为子查询,咱们看rk=1的国家即可

select continent,name,area from (select continent,name,area,rank()over(partition by continent order by area desc) rk from world) r where r.rk=1


很强了吧

难不到你的
下面这个命令也行

select
continent
,name
,area
from world
where (continent,area) in  (selectcontinent,max(area)from worldgroup by continent)

同时满足
即可
这是where的高级用法,咱们同时俩组满足条件

查询法国和意大利每天新增治愈人数并从高到低排名,
查询结果按国家名,截至日期(输出格式为’xxxx年xx月xx日’),新增治愈人数,按排名排序

这里控制条件:德国意大利
from covid
where name in (‘France’,‘Italy’)

covid表

日期标准化

select name,date_format(whn,'%y年%m月%d日') from covid where name in ('France','Italy')


recovered是每天累计治愈
我们每天怎么说?
今天-昨天
昨天怎么表示?lag今天上一天的数据

select name,date_format(whn,'%y年%m月%d日'),recovered-lag(recovered,1)over(partition by name order by whn) xinzeng from covid where name in ('Italy','France')

查询结果按国家名,截至日期(输出格式为’xxxx年xx月xx日’),新增治愈人数,按排名排序

这波要嵌套了,刚刚我们已经查到了他们的新增治愈人数

select name,date_format(whn,'%y年%m月%d日') date,xinzeng,rank()over(partition by name order by xinzeng desc) rk from (select name,whn,recovered-lag(recovered,1)over(partition by name order by whn) xinzeng from covid where name in ('Italy','France')) re order by rk

复杂得一逼

在上面表的基础上,又对新增治愈人数排序
然后根据排序展示结果

嵌套+窗口函数

order by主查询的最后展示结果


这波sql查询语句,咱们就学得差不多
其他的东西,可以暂时不管,数据分析应用岗位是用这个用得最多的

云端数据库配置

本地数据库太吃性能了,不要玩


从百度网盘下载Mysql文件夹
链接:https://pan.baidu.com/s/1-jOwaXWArtv8h21B0-uWGg
提取码:wsra

下一篇文章,我再教你如何配置云端数据库!


总结

提示:重要经验:

1)
2)学好oracle,即使经济寒冬,整个测开offer绝对不是问题!同时也是你考公网络警察的必经之路。
3)笔试求AC,可以不考虑空间复杂度,但是面试既要考虑时间复杂度最优,也要考虑空间复杂度最优。

SQL数据分析:sqlzoo官网学习select,where,order by,limit,聚合函数,having,常用函数,窗口函数,表链接,子查询相关推荐

  1. mySQL学习记录(局域网连接/基础查询/条件查询/常见函数/窗口函数/表连接/子查询/插修删建表)

    一些基础概念 DB 数据库 存储数据的容器 DBMS 数据库管理系统 又称数据库软件.产品如mysql/oracle/db2/sqlserver SQL 结构化查询语言 是所有的DBMS都使用的一种D ...

  2. Spring官网学习(一)概述

    文章目录 1.Spring官网简介 2.Spring总览 2.1.什么是Spring 2.2.Spring的发展历程 3.Spring的设计理念 3.1.Spring的优点 4.IOC和AOP浅析 4 ...

  3. Angular官网学习笔记

    Angular官网学习笔记 一.Angular概述 **什么是Angular:**一个基于TypeScript构建的开发平台包括: 一个基于组件的框架,用于构建可伸缩的Web应用 一组完美集成的库,涵 ...

  4. knockout+html绑定,Knockout.Js官网学习(style绑定、attr绑定)

    Style绑定 style绑定是添加或删除一个或多个DOM元素上的style值.比如当数字变成负数时高亮显示,或者根据数字显示对应宽度的Bar.(注:如果你不是应用style值而是应用CSS clas ...

  5. PCL官网学习OpenNI Grabber 调用奥比中光Astra s 遇到问题openni2_grabber.cpp @ 325 : No devices connected.

    PCL官网学习OpenNI Grabber 调用奥比中光Astra s 遇到问题openni2_grabber.cpp @ 325 : No devices connected. 问题描述 termi ...

  6. Spring AOP官网学习

    Spring AOP官网学习 5.1 AOP概念 让我们从定义一些核心的AOP概念和术语开始.这些术语并不是spring特有的.不幸的是,AOP术语不是特别直观. 1.Aspect(方面):跨多个类的 ...

  7. postgresql 官网学习文档

    pg数据官网学习文档,PostgreSQL: Documentation 中文版:文档目录/Document Index: 世界上功能最强大的开源数据库...

  8. 【PostgreSQL】官网学习使用 PL/pgSQL编写造数据脚本

    文章目录 1. 前言 2. 成果 3. 创建与使用类似 Java map 的数据结构 3.1 声明数组 3.2 数组赋值 3.3 数组遍历 4. 如何打印调试信息 (可以用来生成回滚语句) 5. 后记 ...

  9. Vue 官网学习笔记

    VUE介绍 vue git 地址:https://github.com/vuejs/vue/projects Vue 官网教程地址:https://cn.vuejs.org/v2/guide/inst ...

最新文章

  1. 轻知 | 为什么全球只有13组根域名服务器?
  2. HBase之Region上Spilt流程分析
  3. 系统学习 TypeScript(二)——开发流程和语法规则
  4. 平均值(Mean)、方差(Variance)、标准差(Standard Deviation)
  5. 存储器火热 大陆厂商3倍薪水赴台挖人
  6. Spring装配集合属性
  7. Python教学视频(一)Python基础环境的安装
  8. hdb3编码程序设计c语言,已知代码10000000001011,利用c语言程序编写AMI码跟HDB3码
  9. excel如何把顺序倒过来_excel怎么把顺序倒过来
  10. 企业微信H5_自建应用连接H5
  11. 数理逻辑—24个(16组)重要等值式
  12. MOTO不相信眼泪!艰难回归!你,准备好了吗?
  13. AE新手基础入门教程50套从新手到高手
  14. Portapack应用开发教程(十五) APRS接收
  15. VS未能正确加载 ”Microsoft.VisualStudio.Editor.Implementation.EditorPackate“包错误解决方法...
  16. 迅雷ios版下载beta
  17. 蓄电池内阻、电压及温度在线监测系统应用方案
  18. Coreldraw中选择工具技巧十五招
  19. 谷歌浏览器插件Automa_0.自我见解及官方文档
  20. 【情人节快乐】“我还是很喜欢你就像sin²a+cos²a 始终如一”(附表白代码)

热门文章

  1. nginx 配置域名 http https 80+443端口
  2. 获取今天0时0分0秒时间戳的方法
  3. GH4049高温合金新牌号
  4. Fl Studio 20.8英文切换中文正式版下载及新增功能介绍说明
  5. python爬取微博用户正文_基于Python的新浪微博用户信息爬取与分析
  6. [微信小程序专题] 文本框和页面分割线
  7. java之包装类常用方法
  8. 一本带有插画的软件测试书
  9. 程序员面试之道(《程序员面试笔试宝典》)之求职的时候该不该只看钱?
  10. c++用递归法和迭代法编写函数求Hermite多项式前n项的值