SQL - 每个月采样 n 个用户

SQL - sample n users for each month

我目前正在使用具有属性(user_idcreated_at、...)的 table。我想对自去年 11 月以来每个月创建的 100 到 200 个用户进行抽样。如果我一个月内只 select 100 个用户,那会很容易,因为我可以这样做:

select * from TABLE where created_at >= 'xxxx' and created_at <= 'xxxx'

但我想不出一个干净的方法来为每个月执行此操作,然后将结果放在一起。这有可能以任何方式用 SQL 实现吗?非常感谢。

使用ROW_NUMBER:

SELECT user_id, created_at    -- and other columns
FROM
(
    SELECT *,
        ROW_NUMBER() OVER (PARTITION BY DATE_FORMAT(created_at, '%Y %m')
            ORDER BY created_at DESC) rn
    FROM yourTable
) t
WHERE t.rn <= 100 AND created_at >= '2017-11-01';

我们使用MySQL函数DATE_FORMAT创建每个月和年的分区,然后我们只保留每个分区的100个用户。

如果你的日期真的存储为字符串2018-01-01,那么你可以取字符串的前 7 个字符来获取月份。

然后,使用ROW_NUMBER按月划分,每个月选取前100名用户。

SELECT
    user_id,
    created_at
FROM
    (
        SELECT
            user_id,
            created_at,
            ROW_NUMBER() OVER (PARTITION BY substr(created_at, 1, 7) ORDER BY user_id) AS rn
        FROM T
        WHERE created_at >= '2017-11-01'
    ) AS R
WHERE
    rn <= 100
;

ORDER BY 定义选择哪些用户。上面的查询根据 ID 选择前 100 位用户,这很可能是按照他们创建的顺序,因此查询基本上选择了每个月创建的前 100 位用户。

如果您想要一些随机选择,则按 returns 随机数的函数排序。这看起来更像是 "sample".

SELECT
    user_id,
    created_at
FROM
    (
        SELECT
            user_id,
            created_at,
            ROW_NUMBER() OVER (PARTITION BY substr(created_at, 1, 7) ORDER BY random()) AS rn
        FROM T
        WHERE created_at >= '2017-11-01'
    ) AS R
WHERE
    rn <= 100
;

假设 t-sql 和 created_at 是日期时间。 您可以使用 ROW_NUMBER() (取决于您可以使用几个不同的 rank/row 类型函数之后的特定行为)为每个 year/month 组合生成一个行号。 https://docs.microsoft.com/en-us/sql/t-sql/functions/row-number-transact-sql?view=sql-server-2017

Declare @rows int = 100,
    @date datetime = '2017-11-30'
SELECT *
FROM [YourTable] t
WHERE EXISTS (
    SELECT *
    from(
        Select user_id,
            ROW_NUMBER()OVER(PARTITION BY DATEPART(YEAR, created_at), DATEPART(MONTH, created_at) ORDER BY created_at) as rn
        FROM [YourTable]
        WHERE created_at > @date
        ) as ds
    Where rn <= @rows
    and ds.user_id = t.user_id
    )

编辑:在指定 rdbms 之前写的,除非不合适,否则我会把它留在这里以防其他人偶然发现。

这里有一篇关于使用 NTILE 和 TABLESAMPLE 的博客,我认为这正是您在这里需要的(分层恒定比例采样)。

data-sampling-in-presto