簡體   English   中英

Snowflake - 在使用窗框或訂單時獲取不同用戶的計數

[英]Snowflake - Getting a Count of Distinct Users While Using Window Frame or an Order

我正在嘗試編寫一個查詢來獲取一個月內的累積用戶數。

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

輸出現在如下所示:

在此處輸入圖像描述

問題是我需要計算本月不同或唯一用戶的數量,但此查詢包含天之間用戶的重復。 我知道我不能在我的窗口函數中使用 count(distinct ...) 但是還有另一種方法可以確保我在幾天之間沒有重復用戶嗎?

因此,一個天真的解決方案是將數據轉換為不同的日期和每天不同的用戶,然后將它們加入 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;

給出:

DAY         ACUM_COUNT
2020-03-10  2
2020-03-11  4
2020-03-12  4
2020-03-14  4
2020-03-15  4
2020-03-16  4
2020-03-17  4
2020-03-18  4
2020-03-19  5

在您的 SQL 中,您執行WHERE DATEDIFF('month', HOUR_DIM.UTC, CURRENT_DATE) BETWEEN 0 AND 0WHERE hour_dim.utc >= DATE_TRUNC('month', CURRENT_DATE)會更具可讀性和性能

對此的“聰明”方法是使用dense_rank()的總和:

SELECT first_day, APP_NAME,
       SUM(COUNT(*)) OVER (PARTITION BY APP_NAME ORDER BY first_day ASC) as CUMULATIVE_ACTIVE_USER_ACOUNT
FROM (SELECT CLIENT_SID, APP_NAME,
             MIN(DATE_TRUNC('day', HOUR_DIM.UTC)) as first_day
      FROM RPT.S_HOURLY_INACTIVE_TVS_AGG
      WHERE DATEDIFF('month', HOUR_DIM.UTC, CURRENT_DATE) BETWEEN 0 AND 0
      GROUP BY CLIENT_SID, APP_NAME
     ) cs
GROUP BY first_day, APP_NAME;

如果您每天都有足夠的數據,那么 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

我知道這是舊的,但希望這會幫助任何尋找類似東西的人。

如果您查看 OP 的最后一篇文章,則沒有 3 月 13 日。 正如西蒙所說,他的數據很少。 要每天輸入一個條目,請創建一個日期脊椎。 使用上一篇文章中的 SQL,我調用了一個每天都有一個條目的表(我在下面的示例中將其稱為 DATE_KEY)。 由於這些表往往很遠或很遠,因此我查詢了初始數據集的 min() 和 max() 值,以限制從日期表返回的行。

我在查詢中保留了 first_day 字段,但已將其注釋掉,以便您可以取消注釋以查看日期脊椎與從數據集返回的日期之間的關系。

WITH 
dates AS (
SELECT DATE_KEY
FROM my_date_table
)

,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)
)
,RANGES as (
    SELECT
    min(hour_dim_utc::date) AS min_day
    ,max(hour_dim_utc::date) AS max_day
    FROM data

)
, first_days AS (
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
)

SELECT 
    D.DATE_KEY
    -- ,FD.FIRST_DAY
    ,sum(FD.ACUM) over (ORDER BY DATE_KEY ASC) AS ACUM
FROM DATES D
inner join ranges ON d.date_key >= ranges.min_day and d.date_key <= ranges.max_day
LEFT JOIN FIRST_DAYS FD ON  D.DATE_KEY = FD.FIRST_DAY 

這導致

+------------+------+
|  DATE_KEY  | ACUM |
+------------+------+
| 2020-03-10 |    2 |
| 2020-03-11 |    6 |
| 2020-03-12 |    6 |
| 2020-03-13 |    6 |
| 2020-03-14 |    6 |
| 2020-03-15 |    6 |
| 2020-03-16 |    6 |
| 2020-03-17 |    6 |
| 2020-03-18 |    6 |
| 2020-03-19 |   11 |
+------------+------+

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM