80

我刚刚发现 RAND() 函数虽然没有记录,但可以在 BigQuery 中使用。我能够使用以下方法从莎士比亚数据集中生成(看似)10 个单词的随机样本:

SELECT word FROM
(SELECT rand() as random,word FROM [publicdata:samples.shakespeare] ORDER BY random)
LIMIT 10

我的问题是:使用这种方法而不是参考手册的“高级示例”部分中定义的 HASH() 方法有什么缺点吗?https://developers.google.com/bigquery/query-reference

4

5 回答 5

105

对于分层抽样,请查看https://stackoverflow.com/a/52901452/132438


很好地找到它:)。我最近请求了该功能,但尚未将其写入文档。

我想说 RAND() 的优点是结果会有所不同,而 HASH() 将继续为相同的值提供相同的结果(随着时间的推移不能保证,但你明白了)。

如果您想要 RAND() 带来的可变性同时仍然获得一致的结果 - 您可以使用整数作为种子,如在 RAND(3) 中。

请注意,尽管您粘贴的示例正在执行一种完整的随机值 - 对于足够大的输入,这种方法将无法扩展。

一种可扩展的方法,可以获得大约 10 个随机行:

SELECT word
FROM [publicdata:samples.shakespeare]
WHERE RAND() < 10/164656

其中 10 是我想要获得的大致结果数,164656 是该表的行数


标准 SQL 更新:

#standardSQL
SELECT word
FROM `publicdata.samples.shakespeare`
WHERE RAND() < 10/164656

甚至:

#standardSQL
SELECT word
FROM `publicdata.samples.shakespeare`
WHERE RAND() < 10/(SELECT COUNT(*) FROM `publicdata.samples.shakespeare`)
于 2014-04-29T22:26:19.653 回答
18

很高兴知道 RAND() 可用!

在我的情况下,我需要一个预定义的样本大小。我不需要知道总行数并对总行进行除法样本大小,而是使用以下查询:

SELECT word, rand(5) as rand
FROM [publicdata:samples.shakespeare]
order by rand
#Sample size needed = 10
limit 10

总而言之,我使用 ORDER BY + LIMIT 随机化,然后提取定义数量的样本。

于 2015-11-03T13:17:44.357 回答
12

BigQuery 最近推出了抽样选项,让我们可以从大型 BigQuery 表中随机查询数据子集。我们还可以提及记录的百分比。

例子:

SELECT * FROM dataset.my_table TABLESAMPLE SYSTEM (10 PERCENT)

SELECT *
FROM dataset.table1 T1 TABLESAMPLE SYSTEM (10 PERCENT)
JOIN dataset.table2 T2 TABLESAMPLE SYSTEM (20 PERCENT) ON customer_id

https://cloud.google.com/bigquery/docs/table-sampling

于 2021-04-02T12:36:53.290 回答
8

使其更简单的另一个提示:您可以按其自身的功能订购,即:

通过 rand() 限制 100 从 y 顺序中选择 x

=> 100 个样本

于 2017-09-01T11:46:59.823 回答
3

一旦你计算出你需要多少总百分比,你就可以......

如前所述,一种方法是随机进行非确定性(每次运行=不同的样本),例如,如果您希望对总数据库进行 0.1% 的采样,您可以这样做:

SELECT *
FROM `dataset.table`
WHERE RAND() < 0.001 

实际上,您可以通过保存此表来使其具有确定性,以便以后查询它,您也可以仅选择一个键列并仅保存以供将来使用。


另一种获得相同可重复随机样本的方法是使用加密散列函数生成(唯一标识符字段)列的指纹,然后根据指纹的两位数选择行。下面将标记一个占总数据库 70% 的随机样本。之后,您可以在 in_sample = True 上过滤表:

SELECT
*,
IF(MOD(ABS(FARM_FINGERPRINT(CAST(YOUR_COLUMN AS STRING))), 100) < 70,'True', 'False') 
AS in_sample
FROM (
     SELECT
     DISTINCT(YOUR_UNIQUE_IDENTIFIER_COLUMN) AS YOUR_COLUMN
     FROM
     `dataset.table`)

如果您没有唯一标识符列,您可以连接多个列来组成一个。


与上面类似的方式,但具有散列函数。可重复并为您提供 70% 的样品。如果您想要其他数字,只需将 7 更改为您想要的 %:

SELECT
*
FROM
`dataset.table`
WHERE
ABS(HASH(YOUR_COLUMN)) % 10 < 7

不知道指纹与哈希的可扩展性,所以两者都提到了,对于某些人来说,一个可能比另一个更好。

祝你好运,

于 2020-09-05T13:27:51.283 回答