- 学习:知识的初次邂逅
- 复习:知识的温故知新
练习:知识的实践应用
目录
一,原题力扣链接
二,题干
Insurance
表:+-------------+-------+ | Column Name | Type | +-------------+-------+ | pid | int | | tiv_2015 | float | | tiv_2016 | float | | lat | float | | lon | float | +-------------+-------+ pid 是这张表的主键(具有唯一值的列)。 表中的每一行都包含一条保险信息,其中: pid 是投保人的投保编号。 tiv_2015 是该投保人在 2015 年的总投保金额,tiv_2016 是该投保人在 2016 年的总投保金额。 lat 是投保人所在城市的纬度。题目数据确保 lat 不为空。 lon 是投保人所在城市的经度。题目数据确保 lon 不为空。编写解决方案报告 2016 年 (
tiv_2016
) 所有满足下述条件的投保人的投保金额之和:
- 他在 2015 年的投保额 (
tiv_2015
) 至少跟一个其他投保人在 2015 年的投保额相同。- 他所在的城市必须与其他投保人都不同(也就是说 (
lat, lon
) 不能跟其他任何一个投保人完全相同)。
tiv_2016
四舍五入的 两位小数 。查询结果格式如下例所示。
示例 1:
输入: Insurance 表: +-----+----------+----------+-----+-----+ | pid | tiv_2015 | tiv_2016 | lat | lon | +-----+----------+----------+-----+-----+ | 1 | 10 | 5 | 10 | 10 | | 2 | 20 | 20 | 20 | 20 | | 3 | 10 | 30 | 20 | 20 | | 4 | 10 | 40 | 40 | 40 | +-----+----------+----------+-----+-----+ 输出: +----------+ | tiv_2016 | +----------+ | 45.00 | +----------+ 解释: 表中的第一条记录和最后一条记录都满足两个条件。 tiv_2015 值为 10 与第三条和第四条记录相同,且其位置是唯一的。 第二条记录不符合任何一个条件。其 tiv_2015 与其他投保人不同,并且位置与第三条记录相同,这也导致了第三条记录不符合题目要求。 因此,结果是第一条记录和最后一条记录的 tiv_2016 之和,即 45 。
三,建表语句
Create Table If Not Exists Insurance (pid int, tiv_2015 float, tiv_2016 float, lat float, lon float);
Truncate table Insurance;
insert into Insurance (pid, tiv_2015, tiv_2016, lat, lon) values ('1', '10', '5', '10', '10');
insert into Insurance (pid, tiv_2015, tiv_2016, lat, lon) values ('2', '20', '20', '20', '20');
insert into Insurance (pid, tiv_2015, tiv_2016, lat, lon) values ('3', '10', '30', '20', '20');
insert into Insurance (pid, tiv_2015, tiv_2016, lat, lon) values ('4', '10', '40', '40', '40');
四,分析
题解:
表:保险表
字段:用户投保编号,pid;
2015年的投保金额 tiv_2015;
2016年的投保金额 tiv_2016;
经度和纬度
要求:
条件1:tiv_2015 的金额 要重复;
条件2:经纬度不能重复;
条件3:求出来的tiv_2016 要求四舍五入 保留2位小数
思路一,常规子查询解答
思路
第一步:
以 tiv_2015分组 聚合pid
第二步 对表 添加条件 去除不重复的;拿到最终的
对这个表 别名t1
第三步 创建一个新表 添加一个字段 concat(lat,lon)
第四步 以concat(lat,lon) 分组 聚合count(pid) 拿到
第五步,去除重复的 也就是大于1的
最后一步,观察3个表
中间的表 和左边的表连接 条件是 tiv_2015 = 左表的tiv_2015
在和 右边的表连接 条件是concat(lat,lon) =右表的concat(lat,lon)
然后sum tiv_2016 最后四舍五入 拿到最终的数据
思路二,窗口函数解答
第一步:拼接三个字段
- 第一个字段 concat(lat,lon)
- 第二个字段 co1 以tiv_2015 分组 count pid 然后开窗
- 第三个字段 以 concat(lat,lon) 分组 conut pid 然后开窗
第二步:条件 tiv_2015 允许重复 并且concat(lat,lon)不允许重复
第三步,sum tiv_2016 然后 四舍五入 最后别名 拿到最终的数据
五,SQL解答
解法一,常规子查询解答
with t1 as (
select tiv_2015 as t_2,count(pid) as c_p1 from insurance group by tiv_2015 having count(pid) !=1 -- 左表
),t2 as (
select concat(lat,lon) as cll,count(pid) as c_p from insurance group by concat(lat,lon) having count(pid) =1 -- 右表
),t3 as (
select pid, tiv_2015, tiv_2016, lat, lon,concat(lat,lon) as ll1 from insurance -- 原表 增加字段 concat
),t4 as (
select * from t3 join t1 on t3.tiv_2015 =t1.t_2 -- 三个表内连接 拿到都满足的部分
join t2 on t3.ll1=t2.cll
)
select round(sum(tiv_2016),2) as tiv_2016
from t4
解法二,窗口函数解答
with t1 as (
select pid, tiv_2015, tiv_2016, lat, lon,
concat(lat,lon) as cll,
count(pid) over(partition by tiv_2015) co1,
count(pid) over(partition by concat(lat,lon)) co2
from insurance
)
select round(sum(tiv_2016),2) as tiv_2016 from t1 where t1.co1 != 1 and t1.co2 =1;
六,验证
七,知识点总结
- 分组+聚合+having 判断聚合的列
- concat函数的联系运用
- 三表联查
- sum的运用
- 窗口函数 分组聚合 *2
- 最后条件判断
- 学习:知识的初次邂逅
- 复习:知识的温故知新
练习:知识的实践应用