【问题标题】:Monthly active users in ClickHouseClickHouse 的月活跃用户数
【发布时间】:2019-05-01 07:05:14
【问题描述】:

由于 ClickHouse 不支持用于查询的 WITH 子句,我在实现用于计算 MAU 的查询时遇到了麻烦(每月活跃用户逐日计算,30 天范围也在逐日移动)。 在 Postgres 中我会这样做:

WITH days AS (
  SELECT created_at::DATE AS day,
  FROM events
  WHERE created_at > '2019-04-01'
  GROUP BY 1 
)
SELECT day,
         (SELECT count(distinct user_id)
          FROM events
          WHERE events.created_at::DATE BETWEEN days.day-29 AND days.day
            AND created_at > '2019-04-01'
         ) AS mau
FROM days

想要的结果如下所示

┌────────day─┬──mau─┐
│ 2019-04-04 │ 1278 │
│ 2019-04-05 │ 1375 │
│ 2019-04-06 │ 1162 │
│ 2019-04-07 │ 1237 │
│ 2019-04-08 │ 1272 │
│ 2019-04-09 │ 1263 │
│ 2019-04-10 │ 1336 │
│ 2019-04-11 │ 1457 │
│ 2019-04-12 │ 1286 │
│ 2019-04-13 │ 1210 │
│ 2019-04-14 │ 1253 │
│ 2019-04-15 │ 2342 │
│ 2019-04-16 │ 1464 │
│ 2019-04-17 │ 1513 │
│ 2019-04-18 │ 1158 │
│ 2019-04-19 │ 1207 │
│ 2019-04-20 │ 1222 │
│ 2019-04-21 │ 1054 │
│ 2019-04-22 │ 1505 │
│ 2019-04-23 │ 5287 │
│ 2019-04-24 │ 4367 │
│ 2019-04-25 │ 3624 │
│ 2019-04-26 │ 2415 │
│ 2019-04-27 │ 1962 │
│ 2019-04-28 │ 2032 │
│ 2019-04-29 │ 2547 │
│ 2019-04-30 │ 4059 │
└────────────┴──────┘

【问题讨论】:

    标签: sql clickhouse


    【解决方案1】:

    你可以试试这样的:

    SELECT
        created_at,
        uniqExact(user_id) AS mau
    FROM
    (
        SELECT
            created_at + n AS created_at,
            user_id
        FROM
        (
            SELECT
                today() - 14 AS created_at,
                123 AS user_id
            UNION ALL
            SELECT
                today() - 20 AS created_at,
                456 AS user_id
        )
        ARRAY JOIN range(30) AS n
    )
    WHERE created_at <= today()
    GROUP BY created_at
    FORMAT TSV
    
    2019-04-11  1
    2019-04-12  1
    2019-04-13  1
    2019-04-14  1
    2019-04-15  1
    2019-04-16  1
    2019-04-17  2
    2019-04-18  2
    2019-04-19  2
    2019-04-20  2
    2019-04-21  2
    2019-04-22  2
    2019-04-23  2
    2019-04-24  2
    2019-04-25  2
    2019-04-26  2
    2019-04-27  2
    2019-04-28  2
    2019-04-29  2
    2019-04-30  2
    2019-05-01  2
    
    21 rows in set. Elapsed: 0.005 sec.
    

    【讨论】:

    • 谢谢。它工作正常并且对我来说具有可接受的性能(如果当然有适当的索引)
    【解决方案2】:

    你总是可以只内联 CTE,例如

    SELECT
        d.day,
        COUNT(DISTINCT e.user_id) AS mau
    FROM
    (
        SELECT created_at::DATE AS day,
        FROM events
        WHERE created_at > '2019-04-01'
        GROUP BY 1 
    ) d
    LEFT JOIN events e
        ON e.created_at::DATE BETWEEN d.day-29 AND d.day
    GROUP BY
        d.day;
    

    上面的 CTE 已替换为子查询别名 d。我继续重构您的查询以使用左连接,替换您拥有的相关子查询。

    【讨论】:

    • 很遗憾,由于 ClickHouse 的 SQL 功能受限,我无法使用它。 IE。 JOIN ON 仅支持 '=' 运算符。试图想出一个解决方法...
    • 你能创建一个临时表吗?
    • 嗯,支持临时表,但它使 IMO 变得复杂
    【解决方案3】:

    您还可以创建视图或临时表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-02-21
      • 2020-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-06
      • 1970-01-01
      相关资源
      最近更新 更多