【问题标题】:Postgres, get unique records per day from date range selectPostgres,每天从日期范围选择中获取唯一记录
【发布时间】:2019-06-10 11:55:52
【问题描述】:

我需要按日期范围对登录用户进行报告,但在同一天不重复(如果某人在同一天登录两次,我们不会列出两次)。不幸的是,我们将登录信息保存为 json(是的,我不能将其更改为单独的表,我不知道是谁设计了这个数据库)。 查询查看所有登录用户:

select a.id, username, email, ah.modified as login_date
from accounts a join
     account_history ah
     on modified_acc_id = a.id
 where ah.data::jsonb->>'message' = 'Logon';

修改为带时区的时间戳,作为登录日期。

我只找到了每天计数不同 id 的示例,但我不知道如何修改它以每天返回不同的结果

样本数据:

 id  |        username  |              email       |         login_date
-----+-------------------------+---------------------------------+----------------------------
 102 | example          | example@example.com      | 2018-12-06 09:30:10.573+00
 102 | example          | example@example.com      | 2018-12-06 09:32:34.235+00
  42 | rafal            | rafal@example.com        | 2018-12-06 09:45:24.884+00
 576 | john             | john@example.com         | 2018-12-06 09:35:24.922+00
 576 | john             | john@example.com         | 2018-12-07 09:58:04.253+00

想要的数据:

 id  |        username  |              email       |         login_date
-----+-------------------------+---------------------------------+----------------------------
 102 | example          | example@example.com      | 2018-12-06 09:30:10.573+00
  42 | rafal            | rafal@example.com        | 2018-12-06 09:45:24.884+00
 576 | john             | john@example.com         | 2018-12-06 09:35:24.922+00
 576 | john             | john@example.com         | 2018-12-07 09:58:04.253+00

如你所见,没有第二行

【问题讨论】:

  • @GordonLinoff 已编辑

标签: json postgresql distinct-values


【解决方案1】:

您似乎想要一段时间内的用户天数。如果我理解正确:

select count(*) as num_user_days_in_range
from (select a.username, date_trunc('day', ah.modified) as login_date
      from accounts a join
           account_history ah
           on modified_acc_id = a.id
      where ah.data::jsonb->>'message' = 'Logon'
      group by a.username, login_date
     ) u
where login_date >= $date1 and login_date < $date2

【讨论】:

  • 我编辑了我的问题,我不想要用户数量,只想要每天不同的用户
【解决方案2】:

使用窗口函数row_number()

select id,username,email,login_date from 
(
 select a.id, username, email, ah.modified as login_date,
row_number() over(partition by a.id, username,email order by ah.modified) rn
 from accounts a join
 account_history ah
 on modified_acc_id = a.id
 where ah.data::jsonb->>'message' = 'Logon'
) t where t.rn=1

【讨论】:

    【解决方案3】:

    DISTINCT ON 正好为您提供有序组的第一行。在您的示例中,该组是iddate 部分login_date 时间戳

    SELECT DISTINCT ON (id, login_date::date)
        *
    FROM (
        -- <your query>
    ) s
    ORDER BY id, login_date::date, login_date
    

    demo:db<>fiddle

    ORDER BY子句的解释:

    您必须先按DISTINCT 列排序。但在你的情况下,你真的不想只按日期订购,而是按时间部分订购。因此,在按日期排序后(这是必要的,因为您的 DISTINCT 列)您还必须按时间戳排序。


    所以整个查询可以简化为(没有子查询):

    SELECT DISTINCT ON (a.id, ah.modified::date) 
        a.id, 
        username, 
        email, 
        ah.modified as login_date
    FROM accounts a 
    JOIN account_history ah
        ON modified_acc_id = a.id
    WHERE ah.data::jsonb->>'message' = 'Logon'
    ORDER BY a.id, ah.modified::date, ah.modified 
    

    【讨论】:

      【解决方案4】:

      似乎当有骗局时,你会选择最早的日期。如果是这样,这行得通吗?

      select
        a.id, username, email, min (ah.modified) as login_date
      from accounts a join
           account_history ah
           on modified_acc_id = a.id
       where ah.data::jsonb->>'message' = 'Logon'
      group by a.id, username, email, ah.modified::date
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-01
        • 2020-06-11
        • 2020-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多