1 题目描述
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
四舍五入的两位小数
2 测试用例
输入:
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
3 解题思路
满足条件的投保人:
- 他在 2015 年的投保额 (
tiv_2015
) 至少跟一个其他投保人在 2015 年的投保额相同: 将tiv_2015
分组统计数量tiv_2015_count
, 需要满足tiv_2015_count >= 2
- 他所在的城市必须与其他投保人都不同 (也就是说 (
lat, lon
) 不能跟其他任何一个投保人完全相同) : 将lat, lon
分组统计数量lat_lon_count
,lat_lon_count = 1
- 按照投保额
tiv_2015
统计额度相同的用户数tiv_2015_count
- 按照经纬度
lat, lon
统计地址位置相同的用户数lat_lon_count
select pid,
tiv_2016,
count(*) over (partition by tiv_2015) as tiv_2015_count,
count(*) over (partition by lat,lon) as lat_lon_count
from Insurance
查询结果
+---+--------+--------------+-------------+
|pid|tiv_2016|tiv_2015_count|lat_lon_count|
+---+--------+--------------+-------------+
|1 |5 |3 |1 |
|3 |30 |3 |2 |
|2 |20 |1 |2 |
|4 |40 |3 |1 |
+---+--------+--------------+-------------+
- 将查询数据结果进行筛选
tiv_2015_count >= 2 and lat_lon_count = 1
select i.pid, i.tiv_2016 as tiv_2016
from (select pid,
tiv_2016,
count(*) over (partition by tiv_2015) as tiv_2015_count,
count(*) over (partition by lat,lon) as lat_lon_count
from Insurance) as i
where i.tiv_2015_count > 1
and i.lat_lon_count = 1;
查询结果
+---+--------+
|pid|tiv_2016|
+---+--------+
|1 |5 |
|4 |40 |
+---+--------+
- 将符合条件的投保人信息进行统计
select round(sum(i.tiv_2016), 2) as tiv_2016
from (select tiv_2016,
count(*) over (partition by tiv_2015) as tiv_2015_count,
count(*) over (partition by lat,lon) as lat_lon_count
from Insurance) as i
where i.tiv_2015_count > 1
and i.lat_lon_count = 1;
查询结果
+--------+
|tiv_2016|
+--------+
|45 |
+--------+