【问题标题】:Postgres AggregationsPostgres 聚合
【发布时间】:2020-12-10 10:52:02
【问题描述】:

我有一个如下的 postgres 表

Username Event Date
UserA Log in 02/03/2020 07:06:30
UserA Log in 02/03/2020 10:15:15
UserA Log in 02/03/2020 10:17:01
UserA Log Out 02/03/2020 10:28:55
UserA Log in 02/07/2019 14:56:15
UserA Log in 02/08/2019 10:50:34
UserA Log Out 02/08/2019 10:57:21

试图实现的结果表如下:

Username log_in_Event log_in_Date log_out_event log_out_date
UserA Log in 02/03/2020 07:06:30 null null
UserA Log in 02/03/2020 10:15:15 null null
UserA Log in 02/03/2020 10:17:01 Log Out 02/03/2020 10:28:55
UserA Log in 02/07/2019 14:56:15 null null
UserA Log in 02/08/2019 10:50:34 Log Out 02/08/2019 10:57:21

我已经尝试过的查询如下:

select * from 
(
select  "User Name" , "Event" , "Date" , "IP Address" 
from log_activities log_in 
where "Event" = 'User Logged In'
)log_in
left join 
(
select  "User Name" , "Event" , "Date" , "IP Address" 
from log_activities log_out 
where "Event" = 'User Logged Out'
)log_out
on
log_in."User Name" = log_out."User Name" 
and TO_DATE(log_in."Date" ,'DD/MM/YYYY') = TO_DATE(log_out."Date" ,'DD/MM/YYYY')
and log_in."Date"  < log_out."Date" 
and log_in."IP Address" = log_out."IP Address"

【问题讨论】:

  • 您还没有真正问过问题 - 您当前的输出是什么,您需要什么帮助?
  • 我需要一个查询来帮助我实现第二个表

标签: sql postgresql datetime gaps-and-islands


【解决方案1】:

您可以使用lead解析函数和CASE..WHEN如下:

select t.username, 
       t.event as login_event, 
       t.date as login_date,
       case when t.lead_event = 'Log Out' then t.lead_event end as logout_event, 
       case when t.lead_event = 'Log Out' then t.lead_date end as logout_date
from (select t.*,
             lead(event) over (partition by username order by date) as lead_event,
             lead(date) over (partition by username order by date) as lead_date
      from log_activities t
     ) t
where t.event = 'Log in';

【讨论】:

    【解决方案2】:

    我将此视为“我想要所有登录事件。如果那是下一个事件,我想要下一次注销”。如果是这样,lead() 似乎是最有用的方法:

    select la.username, la.event as login_event, la.date as login_date,
           la.next_event as logout_event, la.next_date as logout_date
    from (select la.*
                 lead(event) over (partition by username order by date) as next_event,
                 lead(date) over (partition by username order by date) as next_date
          from log_activities la
         ) la
    where event = 'Log in';
    

    【讨论】:

    • 谢谢!这行得通!选择此作为正确答案,因为这是我尝试的第一个答案
    【解决方案3】:

    这听起来像是一个孤岛问题。我会推荐一个登录窗口计数来构建组,然后聚合:

    select username, 
        'Log in' as log_in_event,
        min(date) as log_in_date,
        max(event) filter(where event = 'Log Out') as log_out_event,
        max(date)  filter(where event = 'Log Out') as log_out_date
    from (
        select la.*,
            count(*) 
                filter(where event = 'Log in') 
                over(partition by username order by date) as grp
        from log_activities la
    ) la
    group by username, grp
    

    【讨论】:

      猜你喜欢
      • 2014-10-25
      • 2021-11-03
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多