根据最近的日期sql计数

时间:2017-02-27 14:43:56

标签: sql postgresql greatest-n-per-group

我正在尝试计算从他们注册的任何设备进行交易的唯一用户。

这是我的问题:

select Distinct 
    username , 
    case 
       when user_agent like '%Android%' then 'Android'
       when user_agent like '%iPhone%' OR user_agent like '%Iphone%' then     'IOS'
       else 'Internet Banking'
    end as type, 
    min(time)
from
    activeUsers
group by 
    (1, 2); 

但是,在结果集中我得到了这个:

Image Showing query results

我希望例如根据最新日期对用户ujvs24hxen9 / abdallah进行计数,例如,仅在网上银行中计算一次,而不是在网上银行和ios中计算。

我该怎么做?我正在使用postgresql

谢谢!

5 个答案:

答案 0 :(得分:1)

试试这个:

select Distinct username , 
Case When user_agent like '%Android%' then 'Android'
when user_agent like '%iPhone%' OR user_agent like '%Iphone%' then     'IOS'
else 'Internet Banking'
END as type , time
from activeUsers a1
where time = (select max(time) from activeUsers a2 where a1.username = a2.username)

我假设当你说“最近”的时候,你的意思是最大没有时间。

答案 1 :(得分:1)

使用PostgreSQL的DISTINCT ON (username)每个用户只能获得一条记录。使用ORDER BY子句首先获得每个用户所需的记录(即最新的记录):

select distinct on (username)
  username,
  case when user_agent like '%Android%' then 'Android'
       when user_agent like '%iPhone%' 
         or user_agent like '%Iphone%' then  'IOS'
       else 'Internet Banking'
  end as type,
  time
from activeusers
order by username, time desc;

关于你自己的查询:

  • GROUP BY xyz表示您希望每个xyz有一个结果行。在您的查询中,您按前两列进行分组,因此您可以获得每个用户的结果行并输入。但是您只需要每个用户的结果行。因此,在GROUP BY子句中输入内容是没有意义的。
  • DISTINCT从结果中删除重复的行。当您按用户和类型分组并且这两列都被选中时,就不会有重复项;这两列已经使每一行都不同,因此在这些行上应用DISTINCT是多余的。
  • 并且您甚至无法找到每个用户的最新时间并使用它来访问所需的记录。显然这个查询无法正常工作。

答案 2 :(得分:1)

select distinct on (username)
    username,
    case
        when user_agent like '%Android%' then 'Android'
        when user_agent like '%iPhone%' OR user_agent like '%Iphone%' then 'IOS'
        else 'Internet Banking'
    end as type 
    time
from activeUsers
order by username, time desc

答案 3 :(得分:0)

您可以使用row_number窗口函数来获取每个用户的最后一笔交易:

SELECT username, type
FROM   (SELECT username , 
               CASE WHEN user_agent LIKE '%Android%' THEN 'Android'
                    WHEN user_agent LIKE '%iPhone%' OR 
                         user_agent LIKE '%Iphone%' THEN 'IOS'
                    ELSE 'Internet Banking'
        END AS type,
        time
        ROW_NUMBER() OVER (PARTITION BY username ORDER BY time DESC) AS rn
FROM    activeUsers) t
WHERE   rn = 1

答案 4 :(得分:0)

@Mureinik给出的答案的替代方法是使用子查询来标识每个用户的最新时间,然后使用它将原始表限制为我们在结果集中实际需要的记录。

WITH cte AS (
    SELECT username, MAX(time) AS max_time
    FROM activeUsers
    GROUP BY username
)

SELECT t1.username,
       CASE WHEN t1.user_agent LIKE '%Android%' THEN 'Android'
            WHEN t1.user_agent LIKE '%iPhone%' OR t1.user_agent LIKE '%Iphone%' THEN 'IOS'
            ELSE 'Internet Banking'
       END AS type
FROM activeUsers t1
INNER JOIN cte t2
    ON t1.username = t2.username AND
       t1.time     = t2.max_time