SQL实战

学习视频:【课程2.0】SQL从入门到实战|云端数据库搭建|Excel&Tableau连接数据库_哔哩哔哩_bilibili

        由于我学习过SQL,所以直接记录一些函数、特殊用法、刷题等实战的知识,后面教学搭建云端数据库和其他软件连接数据库视频讲解很清晰,也已经全部完成,无需记录,每个题目的类型记录为标题方便查找

通配符

        

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 '% %'

        这一题没什么难度,只是刚开始想的是name like '%a%e%i%o%u%',这样就限制住了元音字母的顺序,不正确,后面的空格用not like即可

指定数据排序到最后

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

        前面一句话很好实现,主要在于排序也就是order by该怎么写,这里的order by有三个排序条件,subject in ('chemistry','physics')是一个布尔表达式,如果subject等于chemistry或physics,那么表达式的结果返回1,否则为0,而后面按照subject升序排列,只有subject等于chemistry或physics的时候为1,其余情况均为0,1自然会被排到0的后面,也就实现了指定科目放在最后的目标

limit用法

select name,population
from world
order by population desc
limit 3,4

        limit普通用法不用多说,但是像这种要取第4到第7的,limit后面第一个数字是第四的前一位就是3,而第二个数字是要查询的个数(4、5、6、7),一共四位数字,就是4

计算表格行数

        计算表格行数要用count(*) ,如果选择某一列count,可能里面出现空值就不会计算上

        同样,聚合函数也会略过空值

常见部分函数

四舍五入函数

        

        

字符串函数

        注意区分:substring和limit,前者是从第n个字符开始取,后者是从n+1个字符开始取

数据类型转换函数

日期时间函数

条件判断函数

round和concat嵌套得到百分比数据

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

        这里主要是使用concat连接函数,在算好的数值后面添加一个%

练习题

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

        这里巧妙地用到了concat函数,我们需要capital匹配'%变化的name%',而使用concat就能使name根据每一行数据变化

高级语句

窗口函数

排序窗口函数区别:

        rank()over():高考排名规则,重复值获得相同序号,如果两行数据排名第1,那么下一行排第3

        dense_rank()over():重复值获得相同序号,如果两行数据排名第1,那么下一行排第2

        row_number()over():不论是否有重复值,每一行获得唯一序号

select yr,party,votes,
rank()over(partition by yr order by votes desc) posn
from ge
where constituency = 'S14000021'
group by yr
order by party,yr

        难点在于如何对每一年中的候选人根据票数高低赋予名次,用到排序窗口函数,partition by yr代表按照日期进行分区,再按照得票数降序排序,由rank给排名

        注意不要太死板,就像这里题目没有要求select yr出来,但是实际当中有日期列看得更加清楚

偏移分析函数

偏移分析函数:

        lag():向前查看多少行,例如lag(column,1),查看上一行column值

        lead():向后查看多少行,例如lag(column,1),查看下一行column值

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 date order by confirmed)) 每天新增确诊人数,
from covid
where name in ('France','Germany') and month(whn) = 1
order by whn

        显示标准日期:使用date_format对时间whn列改格式

        1月份的情况:使用month对whn列取月份

        昨天截至时间累计确诊人数:首先over函数会按照国家名分区,然后按照时间升序排列,接下来lag函数会取上一行的confirmed的值,也就是昨天的confirmed值

        每天新增确诊人数:直接当天-昨天即可

练习题

select party,votes,
rank()over(order by votes desc)
from ge
where yr = 2017 and constituency = 'S14000024'
order by party

        由于我们在where中限制了只有一个选区,所以partition by可以省略

select name 国家名,
confirmed 确诊人数,
rank()over(order by confirmed desc)确诊人数排名,
deaths死亡人数,
rank()over(order by deaths desc)死亡人数排名
from covid
where whn = '2020-04-20'
order by confirmed desc

select name,date_format(whn,'%Y-%m-%d'),
(confirmed - lag(confirmed,1)over(order by whn)) 每周新增人数
from covid
where name = 'Italy' and weekday(whn) = 0
order by whn

        这里变通的地方是显示每周新增人数,一开始想的是写成lag(confirmed - 7)就是当前减去7前的数据,但是我们其实要的只是周一的数据而已,所以在where条件处加上一个weekday(whn) = 0,这样求出来的日期就全部是周一的了,这样仍然用lag(confirmed,1),就是用当周一数据减去上周一数据了

表连接

        内连接:遍历所有、向下增添,相当于笛卡尔积,左边两个1右边两个1,最后会增加4个1,没连上的地方填上null,然后将存在null的行全部剔除

        左连接:遍历所有、向下增添,相当于笛卡尔积,左边两个1右边两个1,最后会增加4个1,没连上的地方填上null,然后保留左边表的全部值,一个不能少一个不能多,左边不允许null存在

        右连接:遍历所有、向下增添,相当于笛卡尔积,左边两个1右边两个1,最后会增加4个1,没连上的地方填上null,然后保留右边表的全部值,一个不能少一个不能多,右边不允许null存在

练习题

select t.name,d.name
from teacher t
left join dept d on t.dept = d.id

        这里要注意的就是‘所有教师’这个词,我们正常用join会发现结果中少了些老师,如果数据太多我们就不容易检查出来,所以还是用左连接可以完全保证教师都在

        还有就是两张表name列同名了,我们需要用表名区分开

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

        where挑选出演过第1主角的人,再having挑选出演过30+次的人

select ga.mdate,

ga.team1,

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

ga.team2,

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

from game ga

left join goal go on ga.id = go.matchid

group by ga.mdate,ga.team1,ga.team2

order by ga.mdate,go.matchid,ga.team1,ga.team2

        这里用了case when这个小技巧,我们看到goal表中teamid对应着game表中team1和team2列的数据,那么我们用case when判断,score1:如果teamid在team1中那么我们就记为1,然后求和。这里也是用left join,因为要保证每场赛事都被记录

子查询

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

        跟这两个国家在同一大洲是我们的条件,而这个条件没办法直接写出来,我们要先求出跟这两个国家在同一大洲的洲有哪些,所以用到子查询

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

        这里比较绕,当我们算出中间那张表也就是找出对每个选区得票进行排序,但是要取出每个每个选区得票数最高的,那么不能直接用limit,那只会返回第一条数据,所以我们在外面再包一张表,查出里面那张表序号为1的,就正确了

        其次就是我们这里虽然只有爱丁堡一个选取,可是这个选区有不同的编号,所以partition by不要省略

        最后这个str也是可以用between and

练习题

select
name
,population
from world
where population > (
                                                 select population
                                                 from world
                                                 where name= 'Canada'
                                      )

and population < (
                                           select population
                                           from world
                                           where name = 'Poland'
                                  )

        不难,就是用两次子查询

select name,population,continent
from world
where continent not in (
    select distinct continent
    from world
    where population > 25000000
)

        这里需要一个反向思维,因为我们需要求国家人口均为<=25000000的大洲,那么正常写continent in(...where population <=25000000...)的话,只要有一个国家符合条件就会把这个大洲算进去,但是我们要求的是每个国家都得符合要求,所以我们可以使用一个not in

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

        这里要求一个区域最大,用子查询可以对洲和区域同时查询,这样都不用distinct了

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

          我觉得第二种做法也可以,就是仿照之前求选举人的做法

select
name
,日期
,每天新增治愈人数
,rank()over(partition by name order by 每天新增治愈人数 desc) 排名
from
(
    select
    name
    ,date_format(whn,'%Y年%m月%d日') 日期
    ,(recovered - lag(recovered,1)over(partition by name order by whn)) 每天新增治愈人数
    from covid
    where name in ('France','Italy')

) re
order by 排名

        这里将之前学些的窗口函数和偏移函数结合在一起,加强练习

云端数据库练习

        创建好云端数据库后,导入学习资料的三张表,然后实战练习

        直接用describe描述shop表,就可以看到表格的总体描述

tips:

  • 如果Mysql导出csv格式数据乱码,是csv文件本身的文本编码问题导致的
    • 1. 鼠标右键点击选中的 csv 文件,在弹出的菜单中选择“编辑”,则系统会用文本方式(记事本)打开该 csv 文件
    • 2. 打开 csv 文件后,进行“另存为”操作,在弹出的界面底部位置有“编码”,修改编码方式即可: 从UTF-8改成 ANSI,然后保存
    • 3. 再用 Excel 打开后,显示汉字正常

        找寻题目中的字段在哪张表中,发现shop表中包含了所有字段,不必连接表,用到之前所学的知识,都能解决

        这里得知GMV和cpc总费用在不同表中,需要连接两张表,这里可以用门店ID和日期两个字段一起作为连接依据,这样有效去除很多重复数据

        接下来我的本意是用left join,这样可以保证所有门店都包含在内,就是会有很多空值

        这里要求和,不是求每天数据那种,每个门店只要最后汇总的数据即可,那么用group by分一下组

        聚合函数不能放在where,所以写在having后面

        我总是喜欢写group by,但是要注意写了group by之后select后的语句就得出现在group by后面

        SQL内容算是复习完了,接下来边学其他内容,边练习牛客网的题目

  • 16
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flink SQL 实战是一个常见的应用场景,可以用于数据处理和分析。下面是一个简单的 Flink SQL 实战示例: 假设你有一个包含用户购买记录的订单表,包括用户ID、购买时间、商品ID和购买数量等字段。你想通过 Flink SQL 来计算每个用户的总购买金额。 首先,你需要将订单表注册为一个 Flink 的表。你可以使用类似下面的代码来实现: ```java StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env); // 创建一个DataStream,读取订单数据 DataStream<Order> orderStream = env.addSource(new OrderSource()); // 注册DataStream为一个表 tableEnv.createTemporaryView("orders", orderStream, "userId, purchaseTime, productId, quantity"); ``` 接下来,你可以使用 Flink SQL 来查询每个用户的总购买金额。可以使用类似下面的代码: ```java // 执行SQL查询,计算每个用户的总购买金额 Table result = tableEnv.sqlQuery("SELECT userId, SUM(quantity) as totalPurchaseAmount " + "FROM orders " + "GROUP BY userId"); // 将结果转换为DataStream输出 DataStream<Result> resultStream = tableEnv.toAppendStream(result, Result.class); // 输出结果 resultStream.print(); ``` 在上面的代码中,我们使用了 Flink SQL 的聚合函数 SUM 和 GROUP BY 来计算每个用户的总购买金额。最后,将结果转换为 DataStream 并打印出来。 这只是一个简单的实例,实际的 Flink SQL 实战涉及到更复杂的查询和处理逻辑。你可以根据具体的业务需求,使用 Flink SQL 来实现更多的数据处理和分析任务。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值