随机样本组而不是 SQL 中的行

Posted

技术标签:

【中文标题】随机样本组而不是 SQL 中的行【英文标题】:Random sample groups instead of rows in SQL 【发布时间】:2021-12-05 14:03:25 【问题描述】:

那么假设我的桌子是这样的:

+---------------------+
|ColA   | ColB | ColC |
+---------------------+
| AA       C        5 |      
| AA       C        8 |     
| AA       C        9 |      
| BB       D        3 |      
| BB       D        4 |    
| CC       E        1 |    
| CC       E        2 |     
| CC       E        3 |     
| CC       E        5 |    
+---------------------+

我想从 COL A 中随机抽样组而不是行。每个组都是一系列事件,我想要每个组的所有这些事件,这就是为什么我不想只对行进行采样。我想像下面这样采样:

+---------------------+
 ColA  | ColB |   ColC 
+---------------------+
| AA       C        5 |      
| AA       C        8 |     
| AA       C        9 |    
| CC       E        1 |      
| CC       E        2 |      
| CC       E        3 |     
| CC       E        5 |      
+---------------------+

下面显然是对行进行采样,所以不好。

SELECT * FROM TABLE TABLE_SAMPLE BERNOULI(1)
GROUP BY COLUMN A

我还有一个包含 10 个组的 COL B,我希望所有这些 qroup 就它们的总行数而言具有相同的表示。谢谢!

【问题讨论】:

您能否添加一些示例数据和所需的输出? 谢谢,我编辑了我的帖子 【参考方案1】:

在 Presto / Trino 中没有直接的方法可以做到这一点。不过,您可以采取几种方法。

如果您需要确定性采样,您可以通过应用统一的哈希函数并选择组的百分比来将组转换为数字。例如:

SELECT *
FROM t
WHERE bitwise_and(from_big_endian_64(xxhash64(cast(a as varbinary))), 1023) <= 0.5 * 1023

它的工作原理:

使用xxhash64 计算分组列的哈希:xxhash64(cast(a as varbinary))。这会产生一个 64 位二进制值。 使用from_big_endian_64 将二进制值转换为一个数字,然后使用bitwise_and(x, 1023) 从中挑选10 位。这会产生一个介于 0 和 1023 之间的数字。 在1% 采样,选择任意组,使上述值小于 0.01 * 1023。

如果您想要对组进行非确定性随机抽样,您可以先对组进行抽样,然后选择与这些组匹配的行:

WITH 
   groups AS (SELECT DISTINCT colA FROM t),
   sampled_groups AS (SELECT * FROM groups TABLESAMPLE BERNOULLI(1)),
SELECT * 
FROM t
WHERE colA IN (TABLE sampled_groups)

【讨论】:

以上是关于随机样本组而不是 SQL 中的行的主要内容,如果未能解决你的问题,请参考以下文章

从 csv 文件生成随机样本,同时跳过具有某些值的行

抽样组而不是行

带组的 SQL 随机样本

来自 Sql 数据库的简单随机样本

随机抽样的 SQL 分区

通过实例详解随机梯度与梯度下降