我目前正在使用具有属性(user_id
,created_at
,...)的表格。我想抽样说自去年11月以来每个月创建的100到200个用户。如果我只从一个月中选择100个用户,那将很容易,因为我可以这样做:
select * from TABLE where created_at >= 'xxxx' and created_at <= 'xxxx'
但我想不出一个干净的方法来每个月做这个,然后把结果放在一起。这有可能以任何方式用SQL实现吗?非常感谢你。
答案 0 :(得分:3)
如果您的日期确实存储为字符串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个用户。
如果您想要一些随机选择,请通过返回随机数的函数进行排序。这看起来更像是一个“样本”。
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
;
答案 1 :(得分:0)
使用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个用户。
答案 2 :(得分:0)
假设t-sql和created_at是一个日期时间。 您可以使用ROW_NUMBER()(取决于您可以使用几个不同的排名/行类型函数后的特定行为)来为每个年/月组合生成行号。 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之前编写,我将把它留在这里以防万一其他人偶然发现,除非不合适。
答案 3 :(得分:0)
这是一个关于使用NTILE和TABLESAMPLE的博客,我认为这正是你所需要的(分层恒定比例抽样)。