检查徽章资格

我们经常收到关于“狂热爱好者(连续 100 天)”徽章的询问。通常的问题是,由于用户所在时区与服务器时区存在差异,用户可能错过了一天或更多天。

我一直对用于授予该徽章的查询有些困惑。不过,我现在认为已经理解了。以下是使用类似逻辑的 Data Explorer 查询。它会返回用户的连续访问时段,包括每个连续访问时段的开始日期、连续天数和结束日期。默认情况下,它返回所有包含 10 次或更多访问的时段。若要查找用户错过了哪些天,请将 min_days 参数设置为 1。

如果返回结果第一行中的 period_end 值等于您运行查询的当前日期,则该用户仍有资格获得该徽章。

--[params]
-- string :username
-- int :min_days = 10

WITH consecutive_visits AS (
  SELECT user_id,
       visited_at,
       -- s 的值对于每个连续天数组是相同的
       visited_at - (DENSE_RANK() OVER (PARTITION BY user_id ORDER BY visited_at))::int s
    FROM user_visits
    WHERE user_id = (SELECT id FROM users WHERE username = :username)
)

SELECT
MIN(visited_at) period_start,
COUNT(*) AS consecutive_days,
MAX(visited_at) period_end
FROM consecutive_visits
GROUP BY user_id, s
HAVING COUNT(*) >= :min_days
ORDER BY period_start DESC