如何加入三个子查询并正确计算交点?

时间:2018-11-22 07:23:40

标签: sql mariadb

我想知道我有多少忠实用户。其定义是,用户每个滚动月份至少需要登录一次。

  

如果用户在2018-08-21和2018-09-21之间登录了一次,并且   在2018-09-21和2018-10-21之间也有一次   2018-10-21和2018-11-21,那么这是一个忠实的用户。

我认为最好的实现方法是加入这三个时间定义的子查询。但是我坚持如何计算呢?每个子查询显示一个不同的计数。我是否必须将最小值视为交点?还是我做错了?

select p.country, round(SUM(a.GBytes+b.GBytes+c.GBytes), 2) as `Traffic`, a.Count, b.Count , c.Count
from (
    SELECT  username, 
            SUBSTRING_INDEX( callingstationid, '=', 1 ) as IP, 
            (SUM(`acctinputoctets`)+SUM(`acctoutputoctets`))/1000/1000/1000 as GBytes, 
            count(username) as Count
    FROM radacct
    WHERE (`acctstarttime` BETWEEN '2018-08-21 22:13:54.286223' AND '2018-09-21 22:13:54.286223')
    GROUP BY username
) a join (
    SELECT  username, 
            SUBSTRING_INDEX( callingstationid, '=', 1 ) as IP, 
            (SUM(`acctinputoctets`)+SUM(`acctoutputoctets`))/1000/1000/1000 as GBytes, 
            count(username) as Count
    FROM radacct
    WHERE (`acctstarttime` BETWEEN '2018-09-21 22:13:54.286223' AND '2018-10-21 22:13:54.286223')
    GROUP BY username
) b on a.username = b.username
join (
    SELECT  username, 
            SUBSTRING_INDEX( callingstationid, '=', 1 ) as IP, 
            (SUM(`acctinputoctets`)+SUM(`acctoutputoctets`))/1000/1000/1000 as GBytes, 
            count(username) as Count
    FROM radacct
    WHERE (`acctstarttime` BETWEEN '2018-10-21 22:13:54.286223' AND '2018-11-21 22:13:54.286223')
    GROUP BY username
) c on b.username = c.username
join cache_db.global_ip p on p.ip = a.IP
join cache_db.global_ip p2 on p2.ip = b.IP
join cache_db.global_ip p3 on p3.ip = c.IP
group by country;

结果: enter image description here

1 个答案:

答案 0 :(得分:1)

由于您只关心用户在每个时间段内至少登录一次,因此无需在每个时间段内对每个用户进行计数。在给定时间段内已连接的任何用户将分别出现在表abc中,并且由于您是JOIN将它们一起放在{{1} }字段,只有在这三个时间段内都已登录的用户才会显示在结果集中。因此,外部查询中的简单username(代替COUNT(*))将为您提供所需的结果。

如果在不同的国家/地区可以使用相同的a.Count, b.Count , c.Count,则需要在每个子查询中按usernameusername分组,并加入countryusername