从 Snowflake 中的表中选择随机百分比(使用 WHERE 子句时)

问题描述 投票:0回答:3

使用此页面作为指南:https://docs.snowflake.com/en/sql-reference/constructs/sample.html

对于本练习,我需要将表中的部分记录按 50/50 拆分:

这些有效。我几乎得到了表行数的 50%:

SELECT * FROM MyTable SAMPLE (50);
SELECT * FROM MyTable TABLESAMPLE (50);

一旦我应用 WHERE 子句,SAMPLE 就不再起作用:

SELECT * FROM MyTable
WHERE country = 'USA' 
AND load_date = CURRENT_DATE
SAMPLE (50);

这让我从上面的雪花页面找到了这个:

方法1;将样本应用于其中一个连接表

select i, j 
    from table1 as t1 inner join table2 as t2 sample (50)
    where t2.j = t1.i 
    ;

方法2;将样本应用于连接表的结果

select * 
   from ( 
         select * 
            from t1 join t2
               on t1.a = t2.c
        ) sample (50);

两种方法都有效,但返回的记录数都是 57%,而不是两种情况下的 50%。

QUALIFY ROW_NUMBER() OVER (ORDER BY RANDOM())
是更好的选择吗?虽然这确实适用于WHERE子句,但我不知道如何设置百分比而不是最大行数。示例:

SELECT * FROM MyTable
WHERE country = 'USA'
AND load_date = CURRENT_DATE
QUALIFY ROW_NUMBER() OVER (ORDER BY RANDOM()) = (50)

--这给了我 50 行,而不是 50% 的行或 4,457 行(本例中 where 子句后的总行数为 8,914)

sql where-clause greatest-n-per-group snowflake-cloud-data-platform window-functions
3个回答
1
投票

在执行 where 子句之前,您需要先对表进行采样。我相信在您的示例中,where 子句首先运行,然后对其进行采样。试试这个(未经测试):

with ct as (
   SELECT * FROM MyTable SAMPLE (50)
)
select 
   *
from ct 
WHERE country = ‘USA’ 
AND load_date = CURRENT_DATE

或者我想:

select 
   *
from (SELECT * FROM MyTable SAMPLE (50))
WHERE country = ‘USA’ 
AND load_date = CURRENT_DATE

0
投票

您可以使用

percent_rank()
代替
row_number()
:

SELECT * FROM MyTable
WHERE country = 'USA'
AND load_date = CURRENT_DATE
QUALIFY PERCENT_RANK() OVER (ORDER BY RANDOM()) <= 0.5

0
投票

SAMPLE(50)
不是一个返回表中 50% 行的功能。这更像是“生成每行的随机数并评估该数字低于或高于百分比”。所以,它不会产生确定性的结果,并且会因为随机性而存在一些偏差。

示例/表格示例 — Snowflake 文档: https://docs.snowflake.com/en/sql-reference/constructs/sample.html

BERNOULLI(或 ROW):以 p/100 的概率包括每一行。类似于为每一行翻转一枚加权硬币。

如果您想以 50/50 的比例将一个表拆分为 2 个数据集,

NTILE()
会很有帮助。

NTILE(n)
是一个函数,通过顺序循环地为每行生成 1 到 n 数字,将有序数据集平均划分为参数中指定的“桶”数量。例如,
NTILE(2) OVER (ORDER BY C1)
会为按
C1
列排序的每一行顺序生成 1, 2, 1, 2, ...,因此您可以使用“BUCKET”列中的值来拆分数据集。

NTILE — 雪花文档: https://docs.snowflake.com/en/sql-reference/functions/ntile.html

将有序数据集均分为constant_value指定的桶数。桶按顺序编号为 1 到constant_value。

因此,如果您想从表中随机提取 50% 的行,可以将

ORDER BY RANDOM()
NTILE()
函数结合使用,如下所示:

with ntiled as (
    select *, ntile(2) over (order by random()) bucket
    from snowflake_sample_data.tpch_sf1.customer
)
select count_if(bucket = 1), count_if(bucket = 2)
from ntiled
;
/*
COUNT_IF(BUCKET = 1)    COUNT_IF(BUCKET = 2)
75000   75000
*/
© www.soinside.com 2019 - 2024. All rights reserved.