BigQuery中,如何随机拆分查询结果?
In BigQuery, how to random split query results?
在 BigQuery(标准 SQL)中,我想 运行domly 从查询中拆分结果行。
拆分需要保持一致,不应随时间变化:意思是每次查询运行时,拆分应该保持不变。
特别是,如果将数据添加到源 table,之前位于拆分一侧的数据应保留在同一拆分中。
该策略应该能够处理不同的分裂比例
例如,我目前有一个 table mytable
,列为 (order_id
、created_at
、country
):
一方面,对于 10%/90% 的分配
SELECT
*
FROM
`mytable`
WHERE RAND() <= 10/90
另一方面
SELECT
*
FROM
`mytable`
WHERE RAND() > 10/90
但这会产生不一致的拆分。有没有办法正确地实现这一目标?
解决方案是在一列上使用 散列函数,该函数可以唯一区分 源 table 的每一行(例如此处 orderId
)。
BigQuery 有一个哈希函数,目标类型是有符号 INT64
(和源 STRING
或 BYTES
):FARM_FINGERPRINT
(来自 here) .
一个解决方案是根据 FARM_FINGERPRINT(orderId)
对每一行进行编码,这是来自所有 INT64
个数字的均匀分布的样本。
对于给定的 k
,MOD(ABS(FARM_FINGERPRINT(orderId)),k)
构成 [0,k-1]
中整数的均匀分布(注意 MOD(a,b)
与 a
负数和 b
正数可能return负数)。
因此,假设您想要 10%/90% 的比例。
每个拆分的查询如下所示:
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),10) = 0
和
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),10) != 0
它可以推广到任何 1/k 拆分:
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),@k) = 0
和
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),@k) != 0
更改判别 mod 整数的值(上面的 0
)允许最多 k
不同的拆分(如果您正在执行多个拆分,这将非常有用-例如在 ML 中进行交叉验证)。
最后但同样重要的是:
- 折叠对于 table
中的数据添加是稳健的
- 折叠保持不变,只要查询是 运行
在 BigQuery(标准 SQL)中,我想 运行domly 从查询中拆分结果行。
拆分需要保持一致,不应随时间变化:意思是每次查询运行时,拆分应该保持不变。
特别是,如果将数据添加到源 table,之前位于拆分一侧的数据应保留在同一拆分中。
该策略应该能够处理不同的分裂比例
例如,我目前有一个 table mytable
,列为 (order_id
、created_at
、country
):
一方面,对于 10%/90% 的分配
SELECT
*
FROM
`mytable`
WHERE RAND() <= 10/90
另一方面
SELECT
*
FROM
`mytable`
WHERE RAND() > 10/90
但这会产生不一致的拆分。有没有办法正确地实现这一目标?
解决方案是在一列上使用 散列函数,该函数可以唯一区分 源 table 的每一行(例如此处 orderId
)。
BigQuery 有一个哈希函数,目标类型是有符号 INT64
(和源 STRING
或 BYTES
):FARM_FINGERPRINT
(来自 here) .
一个解决方案是根据 FARM_FINGERPRINT(orderId)
对每一行进行编码,这是来自所有 INT64
个数字的均匀分布的样本。
对于给定的 k
,MOD(ABS(FARM_FINGERPRINT(orderId)),k)
构成 [0,k-1]
中整数的均匀分布(注意 MOD(a,b)
与 a
负数和 b
正数可能return负数)。
因此,假设您想要 10%/90% 的比例。
每个拆分的查询如下所示:
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),10) = 0
和
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),10) != 0
它可以推广到任何 1/k 拆分:
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),@k) = 0
和
SELECT
*
FROM
`mytable`
WHERE MOD(ABS(FARM_FINGERPRINT(orderId)),@k) != 0
更改判别 mod 整数的值(上面的 0
)允许最多 k
不同的拆分(如果您正在执行多个拆分,这将非常有用-例如在 ML 中进行交叉验证)。
最后但同样重要的是:
- 折叠对于 table 中的数据添加是稳健的
- 折叠保持不变,只要查询是 运行