滚动7天不同活跃用户数

时间:2015-12-08 20:55:19

标签: sql sql-server count distinct moving-average

我正在寻找的输出是每个日期的记录,包括DISTINCT活跃成员的数量和DISTINCT Rolling 7天活跃成员的数量。

我正在使用两个表 - [transactions],它们通过我们的系统记录每笔交易,包括交易处理日期的dmn_date_id,以及DATE_DIMENSION,它在1990年到2020年之间每天都有,day_offset_nbr代表从TODAY()偏移的天数(此表每晚重建)。

SELECT
    dd.date_tms
    , COUNT(DISTINCT(t.user_id)) as Active_Members_Today
    , COUNT(DISTINCT(t2.user_id)) as Rolling_7Day_Active_Members
FROM
    transactions t
    JOIN DATE_DIMENSION dd
        ON t.transaction_processed_date_id = dd.date_id
    JOIN DATE_DIMENSION d2
        ON d2.day_offset_nbr BETWEEN (dd.day_offset_nbr - 6) AND dd.day_offset_nbr
    JOIN transactions t2
        ON d2.dmn_date_id = t2.common_trans_processed_date_id
WHERE
    t.user_initiated_ind = 'Y' -- Only User-initiated Transactions
    AND t2.user_initiated_ind = 'Y'
    AND t.transaction_state_name = 'Accepted' -- Accepted Transactions Only
    AND t2.transaction_state_name = 'Accepted'  
    AND dd.day_offset_nbr >= -731
    AND d2.day_offset_nbr >= -738
GROUP BY
    dd.date_tms

上面的查询得到了我们需要的东西,但需要花费很长时间(超过一小时)来处理。我们已经在user_initiated_ind和common_trans_processed_date_id上​​创建了索引,包括user_id,但查询仍在消失。

以为我可以通过窗口函数解决这个问题,据悉你不能在窗口中使用DISTINCT,这导致我使用带有Row_Number()的派生表来识别窗口内的DISTINCT用户,这让我发现Row_Number()不能与Window ...中的ROWS BETWEEN子句一起使用

我读过Calculate running total / running balance这是类似的,但处理的是运行平衡,而不是滚动不同的计数,我不太确定如何应用我读到的问题;只是我正在使用的INNER JOIN方法被建议不是使用的方法......

......这激励我发帖。

如何改善查询效果?

1 个答案:

答案 0 :(得分:1)

第二次加入transactions似乎完全没必要。您可以使用条件聚合进行计数。所以,这个版本可能会更快:

SELECT d2.date_tms,
       count(distinct case when d2.day_offset_nbr = dd.day_offset_nbr then t.user_id end) as Active_Members_Today,
       count(distinct t.user_id) as Rolling_7Day_Active_Members
FROM transactions t JOIN
     DATE_DIMENSION dd
     ON t.transaction_processed_date_id = dd.date_id JOIN
     DATE_DIMENSION d2
     ON d2.day_offset_nbr BETWEEN dd.day_offset_nbr AND (dd.day_offset_nbr + 6) AND 
WHERE t.user_initiated_ind = 'Y' AND -- Only User-initiated Transactions
      t.transaction_state_name = 'Accepted' AND -- Accepted Transactions Only
      dd.day_offset_nbr >= -731
GROUP BY d2.date_tms;