SQL架构
表:?Calls
+--------------+----------+
| Column Name | Type |
+--------------+----------+
| caller_id | int |
| recipient_id | int |
| call_time | datetime |
+--------------+----------+
(caller_id, recipient_id, call_time) 是这个表的主键。
每一行所含的时间信息都是关于caller_id 和recipient_id的。
编写一个 SQL 查询来找出那些ID们在任意一天的第一个电话和最后一个电话都是和同一个人的。这些电话不论是拨打者还是接收者都会被记录。
结果请放在一个任意次序约束的表中。
查询结果格式如下所示:
输入:
Calls table:
+-----------+--------------+---------------------+
| caller_id | recipient_id | call_time |
+-----------+--------------+---------------------+
| 8 | 4 | 2021-08-24 17:46:07 |
| 4 | 8 | 2021-08-24 19:57:13 |
| 5 | 1 | 2021-08-11 05:28:44 |
| 8 | 3 | 2021-08-17 04:04:15 |
| 11 | 3 | 2021-08-17 13:07:00 |
| 8 | 11 | 2021-08-17 22:22:22 |
+-----------+--------------+---------------------+
输出:
+---------+
| user_id |
+---------+
| 1 |
| 4 |
| 5 |
| 8 |
+---------+
解释:
在 2021-08-24,这天的第一个电话和最后一个电话都是在user 8和user 4之间。user8应该被包含在答案中。
同样的,user 4在2 021-08-24 的第一个电话和最后一个电话都是和user 8的。user 4也应该被包含在答案中。
在 2021-08-11,user 1和5有一个电话。这个电话是他们彼此当天的唯一一个电话。因此这个电话是他们当天的第一个电话也是最后一个电话,他们都应该被包含在答案中。
with t1 as (select
caller_id,recipient_id,call_time #选出 所有id 在某个时间 跟另一个通话的id
from
Calls
union all
select
recipient_id,caller_id,call_time
from
Calls
),
t2 as (
select#按 caller_id 和 每天 分组 对 call_time标号 便于 找到 每天 第一个 和最后的一通电话
caller_id,recipient_id,call_time,row_number() over(partition by caller_id,date_format(call_time,'%Y-%m-%d') order by call_time) rn,row_number() over(partition by caller_id,date_format(call_time,'%Y-%m-%d') order by call_time desc) rn2
from
t1
),
t3 as (
select
caller_id,recipient_id,date_format(call_time,'%Y-%m-%d') day #某天第一次通话
from
t2
where rn = 1
union all
select
caller_id,recipient_id,date_format(call_time,'%Y-%m-%d') day#某天最后一次通话
from
t2
where rn2 = 1
)
select
distinct caller_id user_id
from
t3
group by
caller_id,day #对 某人某天第一次 和最后一次通话的id 去重计数 值为1就是题中需求
having
count(distinct recipient_id)=1
笔记:
select * from ( ? ? select *,row_number() over w as row_num, ? ? from order_tab ? ? WINDOW w AS (partition by product_id order by amount desc) )t ;
window关键字的作用就是为当前窗口起别名。在本语句中,将当前窗口命名为w。 该语句的含义为按照product_id进行分组,并在组内根据amount值进行降序排列。
此处row_number()为窗口函数,参见另一篇文章:MySQL8窗口函数的语法与示例详解
等价于以下语句 select * from ( ? ? select *,row_number() over (partition by product_id order by amount desc) as row_num, ? ? from order_tab ? ? )t ; ———————————————— 版权声明:本文为CSDN博主「程序员先森」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_44848356/article/details/118808946
|