Sql 雪花-在使用窗口框架或订单时获取不同用户的计数

Sql 雪花-在使用窗口框架或订单时获取不同用户的计数,sql,distinct,window-functions,snowflake-cloud-data-platform,Sql,Distinct,Window Functions,Snowflake Cloud Data Platform,我正在尝试编写一个查询,以获取一个月内的累计用户数 WITH USERS_PER_DAY AS ( SELECT DATE_TRUNC('day', HOUR_DIM.UTC) DAY , COUNT(DISTINCT CLIENT_SID) ACTIVE_USER_COUNT FROM RPT.S_HOURLY_INACTIVE_TVS_AGG WHERE DATEDIFF('month', HOUR_DIM.UTC, CURRENT_DATE) BETWEEN 0

我正在尝试编写一个查询,以获取一个月内的累计用户数

WITH USERS_PER_DAY AS (
  SELECT 
    DATE_TRUNC('day', HOUR_DIM.UTC) DAY
  , COUNT(DISTINCT CLIENT_SID) ACTIVE_USER_COUNT
  FROM RPT.S_HOURLY_INACTIVE_TVS_AGG
  WHERE DATEDIFF('month', HOUR_DIM.UTC, CURRENT_DATE) BETWEEN 0 AND 0
  GROUP BY 
    DATE_TRUNC('day', HOUR_DIM.UTC) 
)
SELECT  
DAY,
SUM(ACTIVE_USER_COUNT) OVER (PARTITION BY APP_NAME ORDER BY DAY ASC rows between unbounded preceding and current row) CUMULATIVE_ACTIVE_USER_ACOUNT
FROM USERS_PER_DAY
现在输出如下所示:

问题是,我需要一个月的不同或唯一用户数,但此查询包含两天之间的重复用户数。我知道我不能在我的窗口函数中使用计数(不同的…),但是有没有其他方法可以确保我在两天之间没有重复的用户?

解决这个问题的“聪明”方法是使用
densed\u rank()
s的总和:

“聪明”的方法是使用
densed\u rank()
s的和:


因此,一个简单的解决方案是将数据转换为不同的日期和每天不同的用户,然后将这些数据加入CTE以获得结果:

WITH data AS (  
    select 
        hour_dim_utc::timestamp_ntz as hour_dim_utc
        ,user_id 
    from values
        ('2020-03-10 9:50', 1 ),
        ('2020-03-10 9:51', 3 ),
        ('2020-03-10 10:51', 3 ),
        ('2020-03-11 9:52', 1 ),
        ('2020-03-11 9:53', 2 ),
        ('2020-03-11 9:54', 0 ),
        ('2020-03-12 9:55', 0 ),
        ('2020-03-12 9:56', 1 ),
        ('2020-03-12 9:57', 3 ),
        ('2020-03-14 9:58', 2 ),
        ('2020-03-15 9:59', 3 ),
        ('2020-03-16 10:00', 2 ),
        ('2020-03-17 10:01', 2 ),
        ('2020-03-18 10:02', 0 ),
        ('2020-03-19 10:04', 11 )
         s( hour_dim_utc, user_id)
), distinct_users_days AS (
    select distinct 
        hour_dim_utc::date as day
        ,user_id
    from data
), distinct_days AS (
    select distinct 
        hour_dim_utc::date as day
    from data
)
select 
    a.day
    ,count(distinct(u.user_id)) as acum_count
from distinct_days as a
join distinct_users_days as u on u.day <= a.day
group by 1 order by 1;

在您的SQL中,在0和0之间执行
WHERE DATEDIFF('month',HOUR DIM.UTC,CURRENT_DATE)
如果说
WHERE HOUR DIM.UTC>=DATE TRUNC('month',CURRENT_DATE)
,那么一个简单的解决方案是将数据转换为不同的日期,以及每天不同的用户,然后将其加入CTE以获得结果:

WITH data AS (  
    select 
        hour_dim_utc::timestamp_ntz as hour_dim_utc
        ,user_id 
    from values
        ('2020-03-10 9:50', 1 ),
        ('2020-03-10 9:51', 3 ),
        ('2020-03-10 10:51', 3 ),
        ('2020-03-11 9:52', 1 ),
        ('2020-03-11 9:53', 2 ),
        ('2020-03-11 9:54', 0 ),
        ('2020-03-12 9:55', 0 ),
        ('2020-03-12 9:56', 1 ),
        ('2020-03-12 9:57', 3 ),
        ('2020-03-14 9:58', 2 ),
        ('2020-03-15 9:59', 3 ),
        ('2020-03-16 10:00', 2 ),
        ('2020-03-17 10:01', 2 ),
        ('2020-03-18 10:02', 0 ),
        ('2020-03-19 10:04', 11 )
         s( hour_dim_utc, user_id)
), distinct_users_days AS (
    select distinct 
        hour_dim_utc::date as day
        ,user_id
    from data
), distinct_days AS (
    select distinct 
        hour_dim_utc::date as day
    from data
)
select 
    a.day
    ,count(distinct(u.user_id)) as acum_count
from distinct_days as a
join distinct_users_days as u on u.day <= a.day
group by 1 order by 1;

在您的SQL中,您可以在0和0之间执行
WHERE DATEDIFF('month',HOUR DIM.UTC,CURRENT_DATE)
如果您每天都有足够的数据,那么说
WHERE HOUR DIM.UTC>=DATE TRUNC('month',CURRENT_DATE)
Gordon的更新答案很好,让一个用户在一个月的每一天都有第一天,但是当数据像我的示例数据一样稀疏时,你就不会得到你期望的结果

戈登的准则实际上是这样的:

WITH data AS (  
select hour_dim_utc::timestamp_ntz as hour_dim_utc, user_id from values
    ('2020-03-10 9:50', 1 ),
    ('2020-03-10 9:51', 3 ),
    ('2020-03-10 10:51', 3 ),
    ('2020-03-11 9:52', 1 ),
    ('2020-03-11 9:53', 2 ),
    ('2020-03-11 9:54', 0 ),
    ('2020-03-12 9:55', 0 ),
    ('2020-03-12 9:56', 1 ),
    ('2020-03-12 9:57', 3 ),
    ('2020-03-14 9:58', 2 ),
    ('2020-03-15 9:59', 3 ),
    ('2020-03-16 10:00', 2 ),
    ('2020-03-17 10:01', 2 ),
    ('2020-03-18 10:02', 0 ),
    ('2020-03-19 10:04', 11 )
     s( hour_dim_utc, user_id)
)
select 
    first_day
    ,sum(count(*)) over (ORDER BY first_day ASC) as acum 
from (
    select user_id
        ,min(hour_dim_utc::date) as first_day
    from data 
    group by 1
) group by 1;
其中:

FIRST_DAY   ACUM
2020-03-10  2
2020-03-11  4
2020-03-19  5

Gordon的更新答案是好的,如果你每天都有足够的数据,让用户在一个月的每一天都有第一天,但是当数据像我的示例数据一样稀疏时,你就不会得到你期望的结果

戈登的准则实际上是这样的:

WITH data AS (  
select hour_dim_utc::timestamp_ntz as hour_dim_utc, user_id from values
    ('2020-03-10 9:50', 1 ),
    ('2020-03-10 9:51', 3 ),
    ('2020-03-10 10:51', 3 ),
    ('2020-03-11 9:52', 1 ),
    ('2020-03-11 9:53', 2 ),
    ('2020-03-11 9:54', 0 ),
    ('2020-03-12 9:55', 0 ),
    ('2020-03-12 9:56', 1 ),
    ('2020-03-12 9:57', 3 ),
    ('2020-03-14 9:58', 2 ),
    ('2020-03-15 9:59', 3 ),
    ('2020-03-16 10:00', 2 ),
    ('2020-03-17 10:01', 2 ),
    ('2020-03-18 10:02', 0 ),
    ('2020-03-19 10:04', 11 )
     s( hour_dim_utc, user_id)
)
select 
    first_day
    ,sum(count(*)) over (ORDER BY first_day ASC) as acum 
from (
    select user_id
        ,min(hour_dim_utc::date) as first_day
    from data 
    group by 1
) group by 1;
其中:

FIRST_DAY   ACUM
2020-03-10  2
2020-03-11  4
2020-03-19  5

谢谢你的回复。然而,这似乎不适合我。它会生成一个每天有50个用户的表。@JamesD。我有个错误的想法。我只是完全重写了答案。关键的想法是为每个用户获取第一个日期,然后将其相加。只要您至少有一个用户每天都有他们的
第一天
,这一点就行了。感谢您的回复。然而,这似乎不适合我。它会生成一个每天有50个用户的表。@JamesD。我有个错误的想法。我只是完全重写了答案。关键的想法是为每个用户获取第一个日期,然后将其相加。只要您至少有一个用户每天都有他们的
第一天
,这种方法就行了。