1699. 两人之间的通话次数

问题:
查询每一对用户 (person1, person2) 之间的通话次数和通话总时长,其中 person1 < person2

表: Calls

+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| from_id     | int     |
| to_id       | int     |
| duration    | int     |
+-------------+---------+
该表没有主键,可能存在重复项。
该表包含 from_id 与 to_id 间的一次电话的时长。
from_id != to_id

查询结果格式如下示例所示。

示例 1:

Calls 表:
+---------+-------+----------+
| from_id | to_id | duration |
+---------+-------+----------+
| 1       | 2     | 59       |
| 2       | 1     | 11       |
| 1       | 3     | 20       |
| 3       | 4     | 100      |
| 3       | 4     | 200      |
| 3       | 4     | 200      |
| 4       | 3     | 499      |
+---------+-------+----------+
输出:
+---------+---------+------------+----------------+
| person1 | person2 | call_count | total_duration |
+---------+---------+------------+----------------+
| 1       | 2       | 2          | 70             |
| 1       | 3       | 1          | 20             |
| 3       | 4       | 4          | 999            |
+---------+---------+------------+----------------+
解释:
用户 1 和 2 打过 2 次电话,总时长为 70 (59 + 11)。
用户 1 和 3 打过 1 次电话,总时长为 20。
用户 3 和 4 打过 4 次电话,总时长为 999 (100 + 200 + 200 + 499)
drop table if EXISTS Calls;
Create table If Not Exists Calls (from_id int, to_id int, duration int);

insert into Calls values (1,2,59);
insert into Calls values (2,1,11);
insert into Calls values (1,3,20);
insert into Calls values (3,4,100);
insert into Calls values (3,4,200);
insert into Calls values (3,4,200);
insert into Calls values (4,3,499);

select * from Calls;

用的 abs( ) 和 +:

select
    min(from_id) person1,max(to_id) person2,count(duration) call_count,sum(duration) total_duration
    -- 分组后会有 类似于 1,2 或者 2,1的数据 用 min() 和 max() 保证 person1 < person2
from
    Calls
group by abs(from_id-to_id),from_id+to_id -- 两数之差的绝对值相同,且两数之和相同,则两个数的组合是唯一的

用的 if:

SELECT
    person1,person2,
    count(*) call_count,
    sum(duration) total_duration
FROM (
         SELECT
             IF(from_id>to_id, to_id, from_id) person1,
             IF(from_id>to_id,from_id,to_id) person2,
             duration
         FROM calls
     ) c
GROUP BY
    person1, person2

union all:

SELECT tmp.person1,tmp.person2,COUNT(1) call_count,SUM(duration) total_duration FROM(
                                                                                        SELECT from_id person1,to_id person2,duration FROM calls WHERE from_id<to_id
                                                                                        UNION ALL
                                                                                        SELECT to_id person1,from_id person2,duration FROM calls WHERE from_id>to_id
                                                                                    ) tmp
GROUP BY tmp.person1,tmp.person2

用的least() 和 greatest():

select
    from_id as person1,
    to_id as person2,
    count(1) as call_count,
    sum(duration) as total_duration
from calls
group by least(from_id, to_id),greatest(from_id, to_id)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值