彙總函數

概觀

彙總函數對一組值進行運算以計算單一結果。

除了 count()count_if()max_by()min_by()approx_distinct() 之外,所有這些彙總函數都會忽略空值,並且在沒有輸入列或所有值都為空時會傳回空值。例如,sum() 會傳回空值而不是零,而 avg() 不會在計數中包含空值。coalesce 函數可用於將空值轉換為零。

某些彙總函數(例如 array_agg())會根據輸入值的順序產生不同的結果。此排序可以透過在彙總函數中寫入 ORDER BY 子句 來指定

array_agg(x ORDER BY y DESC)
array_agg(x ORDER BY x, y, z)

一般彙總函數

any_value(x) -> [與輸入相同]()

這是 arbitrary() 的別名。

arbitrary(x) -> [與輸入相同]()

如果存在,則傳回 x 的任意非空值。

array_agg(x) -> array<[與輸入相同]>()

傳回從輸入 x 元素建立的陣列。

avg(x) -> double()

傳回所有輸入值的平均值(算術平均數)。

avg(時間間隔類型) -> 時間間隔類型()

傳回所有輸入值的平均間隔長度。

bool_and(boolean) -> boolean()

如果所有輸入值皆為 TRUE,則返回 TRUE,否則返回 FALSE

bool_or(boolean) -> boolean()

如果任一輸入值為 TRUE,則返回 TRUE,否則返回 FALSE

checksum(x) -> varbinary()

返回給定值的順序無關的校驗和。

count(*) -> bigint()

返回輸入的列數。

count(x) -> bigint()

返回非 null 輸入值的數量。

count_if(x) -> bigint()

返回 TRUE 輸入值的數量。此函數等同於 count(CASE WHEN x THEN 1 END)

every(boolean) -> boolean()

這是 bool_and() 的別名。

geometric_mean(bigint) -> double()
geometric_mean(double) -> double()
geometric_mean(real) -> real()

返回所有輸入值的幾何平均數

max_by(x, y) -> [與 x 相同]()

返回與所有輸入值中 y 的最大值相關聯的 x 值。

max_by(x, y, n) -> array<[與 x 相同]>()

返回與 y 的所有輸入值中最大的 n 個值相關聯的 xn 個值,並依 y 的遞減順序排列。

min_by(x, y) -> [與 x 相同]()

返回與所有輸入值中 y 的最小值相關聯的 x 值。

min_by(x, y, n) -> array<[與 x 相同]>()

返回與 y 的所有輸入值中最小的 n 個值相關聯的 xn 個值,並依 y 的遞增順序排列。

max(x) -> [與輸入相同]()

返回所有輸入值的最大值。

max(x, n) -> array<[與 x 相同]>()

返回 x 的所有輸入值中最大的 n 個值。

min(x) -> [與輸入相同]()

返回所有輸入值的最小值。

min(x, n) -> array<[與 x 相同]>()

返回 x 的所有輸入值中最小的 n 個值。

reduce_agg(inputValue T, initialState S, inputFunction(S,T,S), combineFunction(S,S,S)) -> S()

將所有輸入值簡化為單一值。inputFunction 將針對每個輸入值調用。除了獲取輸入值之外,inputFunction 還會獲取目前狀態(最初為 initialState),並返回新的狀態。combineFunction 將被調用以將兩個狀態合併成一個新狀態。返回最終狀態。如果 initialState 為 NULL,則會擲回錯誤。如果 inputFunctioncombineFunction 返回 NULL,則行為未定義。

設計 initialStateinputFunctioncombineFunction 時請注意。這些必須支援使用許多節點上的部分聚合來分散式評估聚合,然後再在群組依據鍵上進行混洗,最後再進行最終聚合。考慮所有可能的狀態值,以確保 combineFunction可交換結合運算,且 initialState單位值。

對於任何 s,combineFunction(s, initialState) = s

對於任何 s1 和 s2,combineFunction(s1, s2) = combineFunction(s2, s1)

對於任何 s1、s2 和 s3,combineFunction(s1, combineFunction(s2, s3)) = combineFunction(combineFunction(s1, s2), s3)

此外,請確保以下內容適用於 inputFunction

對於任何 x 和 y,inputFunction(inputFunction(initialState, x), y) = combineFunction(inputFunction(initialState, x), inputFunction(initialState, y))

SELECT id, reduce_agg(value, 0, (a, b) -> a + b, (a, b) -> a + b)
FROM (
    VALUES
        (1, 2),
        (1, 3),
        (1, 4),
        (2, 20),
        (2, 30),
        (2, 40)
) AS t(id, value)
GROUP BY id;
-- (1, 9)
-- (2, 90)

SELECT id, reduce_agg(value, 1, (a, b) -> a * b, (a, b) -> a * b)
FROM (
    VALUES
        (1, 2),
        (1, 3),
        (1, 4),
        (2, 20),
        (2, 30),
        (2, 40)
) AS t(id, value)
GROUP BY id;
-- (1, 24)
-- (2, 24000)

狀態類型必須是布林值、整數、浮點數或日期/時間/間隔。

set_agg(x) -> array<[與輸入相同]>()

返回由不同的輸入 x 元素建立的陣列。

如果輸入包含 NULL,則返回的陣列中將包含 NULL。如果輸入包含具有 NULL 元素的陣列或具有 NULL 欄位的列,則它們將包含在返回的陣列中。此函數使用 IS DISTINCT FROM 來判斷相異性。

SELECT set_agg(x) FROM (VALUES(1), (2), (null), (2), (null)) t(x) -- ARRAY[1, 2, null]
SELECT set_agg(x) FROM (VALUES(ROW(ROW(1, null))), ROW((ROW(2, 'a'))), ROW((ROW(1, null))), (null)) t(x) -- ARRAY[ROW(1, null), ROW(2, 'a'), null]
set_union(array(T)) -> array(T)

傳回一個陣列,其中包含輸入的每個陣列中所有不同的值。

當所有輸入都是 NULL 時,此函數會傳回一個空陣列。如果 NULL 是其中一個輸入陣列的元素,則 NULL 將會包含在傳回的陣列中。如果輸入包含具有 NULL 元素的陣列,或具有 NULL 欄位的列,它們也會包含在傳回的陣列中。此函數使用 IS DISTINCT FROM 來判斷是否相異。

範例

SELECT set_union(elements)
FROM (
    VALUES
        ARRAY[1, 2, 3],
        ARRAY[2, 3, 4]
) AS t(elements);

傳回 ARRAY[1, 2, 3, 4]

sum(x) -> [與輸入相同]()

傳回所有輸入值的總和。

位元聚合函數

bitwise_and_agg(x) -> bigint()

傳回所有輸入值以二補數表示的位元 AND 結果。

bitwise_or_agg(x) -> bigint()

傳回所有輸入值以二補數表示的位元 OR 結果。

bitwise_xor_agg(x) -> bigint()

傳回所有輸入值以二補數表示的位元 XOR 結果。

映射聚合函數

histogram(x) -> map(K, bigint)

傳回一個映射,其中包含每個輸入值出現次數的計數。

map_agg(key, value) -> map(K, V)

傳回從輸入的 key / value 配對建立的映射。

map_union(x(K, V)) -> map(K, V)

傳回所有輸入映射的聯集。如果一個鍵在多個輸入映射中找到,則結果映射中該鍵的值來自任意的輸入映射。

map_union_sum(x(K, V)) -> map(K, V)

傳回所有輸入映射的聯集,並將所有映射中匹配鍵的值加總。原始映射中的所有 null 值都會合併為 0。

multimap_agg(key, value) -> map(K, array(V))

傳回從輸入的 key / value 配對建立的多重映射。每個鍵可以與多個值相關聯。

近似聚合函數

approx_distinct(x) -> bigint()

傳回不同的輸入值的大約數量。此函數提供 count(DISTINCT x) 的近似值。如果所有輸入值都是 null,則傳回零。

此函數應產生 2.3% 的標準誤差,這是所有可能集合的(近似常態)誤差分布的標準差。它不保證任何特定輸入集的誤差上限。

approx_distinct(x, e) -> bigint()

傳回不同的輸入值的大約數量。此函數提供 count(DISTINCT x) 的近似值。如果所有輸入值都是 null,則傳回零。

此函數應產生的標準誤差不超過 e,這是所有可能集合的(近似常態)誤差分佈的標準差。它不保證任何特定輸入集的誤差上限。此函數的目前實作要求 e 的範圍在 [0.0040625, 0.26000] 之間。

approx_percentile(x, percentage) -> [與 x 相同]()

傳回在給定 percentage 時,所有 x 輸入值的近似百分位數。percentage 的值必須介於 0 和 1 之間,且對於所有輸入列必須是常數。

approx_percentile(x, percentage, accuracy) -> [與 x 相同]()

approx_percentile(x, percentage) 相同,但最大排序誤差為 accuracyaccuracy 的值必須介於 0 和 1 之間(不包含),且對於所有輸入列必須是常數。請注意,較低的「accuracy」實際上是較低的錯誤門檻,因此更準確。預設的 accuracy 為 0.01

approx_percentile(x, percentages) -> array<[與 x 相同]>()

傳回在每個指定的百分比處,所有 x 輸入值的近似百分位數。percentages 陣列的每個元素都必須介於 0 和 1 之間,且該陣列對於所有輸入列必須是常數。

approx_percentile(x, percentages, accuracy) -> array<[與 x 相同]>()

approx_percentile(x, percentages) 相同,但最大排序誤差為 accuracy

approx_percentile(x, w, percentage) -> [與 x 相同]()

使用每個項目的權重 w,在百分比 p 的位置,傳回 x 所有輸入值的近似加權百分位數。權重必須是至少為 1 的整數值。它實際上是百分位數集中 x 值的重複計數。p 的值必須介於 0 和 1 之間,且對於所有輸入列必須為常數。

approx_percentile(x, w, percentage, accuracy) -> [與 x 相同]()

approx_percentile(x, w, percentage) 相同,但最大排名誤差為 accuracy

approx_percentile(x, w, percentages) -> array<[與 x 相同]>()

使用每個項目的權重 w,在陣列中指定的每個給定百分比位置,傳回 x 所有輸入值的近似加權百分位數。權重必須是至少為 1 的整數值。它實際上是百分位數集中 x 值的重複計數。陣列的每個元素必須介於 0 和 1 之間,且對於所有輸入列,該陣列必須為常數。

approx_percentile(x, w, percentages, accuracy) -> array<[與 x 相同]>()

approx_percentile(x, w, percentages) 相同,但最大排名誤差為 accuracy

approx_set(x) -> HyperLogLog()

請參閱 HyperLogLog 函數

merge(x) -> HyperLogLog()

請參閱 HyperLogLog 函數

khyperloglog_agg(x) -> KHyperLogLog()

請參閱 KHyperLogLog 函數

merge(qdigest(T)) -> qdigest(T)

請參閱 Quantile Digest 函數

qdigest_agg(x) -> qdigest<[與 x 相同]>()

請參閱 Quantile Digest 函數

qdigest_agg(x, w) -> qdigest<[與 x 相同]>()

請參閱 Quantile Digest 函數

qdigest_agg(x, w, accuracy) -> qdigest<[與 x 相同]>()

請參閱 Quantile Digest 函數

numeric_histogram(buckets, value, weight) -> map<double, double>()

針對所有 value 值,使用每個項目的權重 weight,計算最多 buckets 個儲存桶的近似直方圖。傳回的映射的鍵大致是儲存桶的中心,而項目是儲存桶的總權重。此演算法大致基於 [BenHaimTomTov2010]

buckets 必須為 bigintvalueweight 必須為數值。

numeric_histogram(buckets, value) -> map<double, double>()

針對所有 value 值,計算最多 buckets 個儲存桶的近似直方圖。此函式等同於使用權重的 numeric_histogram() 變體,其中每個項目的權重為 1。在此情況下,傳回的映射中的總權重是儲存桶中項目的計數。

統計彙總函數

corr(y, x) -> double()

傳回輸入值的相關係數。

covar_pop(y, x) -> double()

傳回輸入值的母體共變異數。

covar_samp(y, x) -> double()

傳回輸入值的樣本共變異數。

entropy(c) -> double()

傳回計數輸入值的以 2 為底的對數熵。

\[\mathrm{entropy}(c) = \sum_i \left[ {c_i \over \sum_j [c_j]} \log_2\left({\sum_j [c_j] \over c_i}\right) \right].\]

c 必須是非負值的 bigint 欄。

此函式會忽略任何 NULL 計數。如果非 NULL 計數的總和為 0,則會傳回 0。

kurtosis(x) -> double()

傳回所有輸入值的超額峰度。使用下列運算式的不偏估計

\[\mathrm{kurtosis}(x) = {n(n+1) \over (n-1)(n-2)(n-3)} { \sum[(x_i-\mu)^4] \over \sigma^4} -3{ (n-1)^2 \over (n-2)(n-3) }\]

其中 \(\mu\) 是平均值,而 \(\sigma\) 是標準差。

regr_intercept(y, x) -> double()

傳回輸入值的線性迴歸截距。y 是相依值。x 是獨立值。

regr_slope(y, x) -> double()

傳回輸入值的線性迴歸斜率。y 是相依值。x 是獨立值。

regr_avgx(y, x) -> double()

傳回群組中獨立值的平均值。y 是相依值。x 是獨立值。

regr_avgy(y, x) -> double()

傳回群組中依賴值的平均值。y 是依賴值。x 是獨立值。

regr_count(y, x) -> double()

傳回非空輸入值配對的數量。y 是依賴值。x 是獨立值。

regr_r2(y, x) -> double()

傳回線性迴歸的判定係數。y 是依賴值。x 是獨立值。

regr_sxy(y, x) -> double()

傳回群組中依賴值和獨立值的乘積總和。y 是依賴值。x 是獨立值。

regr_syy(y, x) -> double()

傳回群組中依賴值的平方和。y 是依賴值。x 是獨立值。

regr_sxx(y, x) -> double()

傳回群組中獨立值的平方和。y 是依賴值。x 是獨立值。

skewness(x) -> double()

傳回所有輸入值的偏度。

stddev(x) -> double()

這是 stddev_samp() 的別名。

stddev_pop(x) -> double()

傳回所有輸入值的母體標準差。

stddev_samp(x) -> double()

傳回所有輸入值的樣本標準差。

variance(x) -> double()

這是 var_samp() 的別名。

var_pop(x) -> double()

傳回所有輸入值的母體變異數。

var_samp(x) -> double()

傳回所有輸入值的樣本變異數。

分類指標彙總函數

以下每個函數都會測量二元混淆矩陣的某些指標如何隨著分類閾值的函數而變化。它們旨在結合使用。

例如,若要尋找精確率-召回率曲線,請使用

WITH
    recall_precision AS (
        SELECT
            CLASSIFICATION_RECALL(10000, correct, pred) AS recalls,
            CLASSIFICATION_PRECISION(10000, correct, pred) AS precisions
        FROM
           classification_dataset
    )
SELECT
    recall,
    precision
FROM
    recall_precision
CROSS JOIN UNNEST(recalls, precisions) AS t(recall, precision)

若要取得這些值的對應閾值,請使用

WITH
    recall_precision AS (
        SELECT
            CLASSIFICATION_THRESHOLDS(10000, correct, pred) AS thresholds,
            CLASSIFICATION_RECALL(10000, correct, pred) AS recalls,
            CLASSIFICATION_PRECISION(10000, correct, pred) AS precisions
        FROM
           classification_dataset
    )
SELECT
    threshold,
    recall,
    precision
FROM
    recall_precision
CROSS JOIN UNNEST(thresholds, recalls, precisions) AS t(threshold, recall, precision)

若要尋找 ROC 曲線,請使用

WITH
    fallout_recall AS (
        SELECT
            CLASSIFICATION_FALLOUT(10000, correct, pred) AS fallouts,
            CLASSIFICATION_RECALL(10000, correct, pred) AS recalls
        FROM
           classification_dataset
    )
SELECT
    fallout
    recall,
FROM
    recall_fallout
CROSS JOIN UNNEST(fallouts, recalls) AS t(fallout, recall)
classification_miss_rate(buckets, y, x, weight) -> array<double>()

計算最多使用 buckets 個儲存桶的遺漏率。傳回遺漏率值的陣列。

y 應該是布林值結果值;x 應該是預測值,每個值介於 0 和 1 之間;weight 應該是非負值,表示實例的權重。

遺漏率定義為一個序列,其第 \(j\) 個項目為

\[{ \sum_{i \;|\; x_i \leq t_j \bigwedge y_i = 1} \left[ w_i \right] \over \sum_{i \;|\; x_i \leq t_j \bigwedge y_i = 1} \left[ w_i \right] + \sum_{i \;|\; x_i > t_j \bigwedge y_i = 1} \left[ w_i \right] },\]

其中 \(t_j\) 是第 \(j\) 個最小的閾值,而 \(y_i\)\(x_i\)\(w_i\) 分別是 yxweight 的第 \(i\) 個項目。

classification_miss_rate(buckets, y, x) -> array<double>()

此函數等同於採用 weightclassification_miss_rate() 變體,其中每個項目的權重為 1

classification_fall_out(buckets, y, x, weight) -> array<double>()

計算最多使用 buckets 個儲存桶的假警報率。傳回假警報率值的陣列。

y 應該是布林值結果值;x 應該是預測值,每個值介於 0 和 1 之間;weight 應該是非負值,表示實例的權重。

假警報率定義為一個序列,其第 \(j\) 個項目為

\[{ \sum_{i \;|\; x_i > t_j \bigwedge y_i = 0} \left[ w_i \right] \over \sum_{i \;|\; y_i = 0} \left[ w_i \right] },\]

其中 \(t_j\) 是第 \(j\) 個最小的閾值,而 \(y_i\)\(x_i\)\(w_i\) 分別是 yxweight 的第 \(i\) 個項目。

classification_fall_out(buckets, y, x) -> array<double>()

此函數等同於採用 weightclassification_fall_out() 變體,其中每個項目的權重為 1

classification_precision(buckets, y, x, weight) -> array<double>()

計算最多使用 buckets 個儲存桶的精確率。傳回精確率值的陣列。

y 應該是布林值結果值;x 應該是預測值,每個值介於 0 和 1 之間;weight 應該是非負值,表示實例的權重。

精確率定義為一個序列,其第 \(j\) 個項目為

\[{ \sum_{i \;|\; x_i > t_j \bigwedge y_i = 1} \left[ w_i \right] \over \sum_{i \;|\; x_i > t_j} \left[ w_i \right] },\]

其中 \(t_j\) 是第 \(j\) 個最小的閾值,而 \(y_i\)\(x_i\)\(w_i\) 分別是 yxweight 的第 \(i\) 個項目。

classification_precision(buckets, y, x) -> array<double>()

此函數等同於採用 weightclassification_precision() 變體,其中每個項目的權重為 1

classification_recall(buckets, y, x, weight) -> array<double>()

計算最多 buckets 個桶子的召回率。返回一個包含召回率值的陣列。

y 應該是布林值結果值;x 應該是預測值,每個值介於 0 和 1 之間;weight 應該是非負值,表示實例的權重。

召回率定義為一個序列,其第 \(j\) 個條目為

\[{ \sum_{i \;|\; x_i > t_j \bigwedge y_i = 1} \left[ w_i \right] \over \sum_{i \;|\; y_i = 1} \left[ w_i \right] },\]

其中 \(t_j\) 是第 \(j\) 個最小的閾值,而 \(y_i\)\(x_i\)\(w_i\) 分別是 yxweight 的第 \(i\) 個項目。

classification_recall(buckets, y, x) -> array<double>()

此函數等同於接受 weight 參數的 classification_recall() 變體,其中每個項目的權重為 1

classification_thresholds(buckets, y, x) -> array<double>()

計算最多 buckets 個桶子的閾值。返回一個包含閾值值的陣列。

y 應該是一個布林結果值; x 應該是預測值,每個值介於 0 和 1 之間。

閾值定義為一個序列,其第 \(j\) 個條目是第 \(j\) 個最小的閾值。

微分熵函數

以下函數近似二元 微分熵。也就是說,對於一個隨機變數 \(x\),它們近似

\[h(x) = - \int x \log_2\left(f(x)\right) dx,\]

其中 \(f(x)\)\(x\) 的部分密度函數。

differential_entropy(sample_size, x)

從隨機變數的樣本結果返回近似的 log-2 微分熵。該函數內部會建立一個儲存庫 (請參閱 [Black2015]),然後透過近似累積分佈的導數 (請參閱 [Alizadeh2010]) 從樣本結果計算熵。

sample_size (long) 是儲存庫樣本的最大數量。

x (double) 是樣本。

例如,要使用 1000000 個儲存庫樣本找到 datax 的微分熵,請使用

SELECT
    differential_entropy(1000000, x)
FROM
    data

注意

如果 \(x\) 有已知的下限和上限,建議使用採用 (bucket_count, x, 1.0, "fixed_histogram_mle", min, max)(bucket_count, x, 1.0, "fixed_histogram_jacknife", min, max) 的版本,因為它們具有更好的收斂性。

differential_entropy(sample_size, x, weight)

從隨機變數的樣本結果返回近似的 log-2 微分熵。該函數內部會建立一個加權儲存庫 (請參閱 [Efraimidis2006]),然後透過近似累積分佈的導數 (請參閱 [Alizadeh2010]) 從樣本結果計算熵。

sample_size 是儲存庫樣本的最大數量。

x (double) 是樣本。

weight (double) 是一個非負的 double 值,表示樣本的權重。

例如,要使用 1000000 個儲存庫樣本找到 data 中具有權重 weightx 的微分熵,請使用

SELECT
    differential_entropy(1000000, x, weight)
FROM
    data

注意

如果 \(x\) 有已知的下限和上限,建議使用採用 (bucket_count, x, weight, "fixed_histogram_mle", min, max)(bucket_count, x, weight, "fixed_histogram_jacknife", min, max) 的版本,因為它們具有更好的收斂性。

differential_entropy(bucket_count, x, weight, method, min, max) -> double()

從隨機變數的樣本結果返回近似的 log-2 微分熵。該函數內部會建立樣本值的概念直方圖,計算計數,然後根據 method 參數,使用最大似然估計 (有或沒有 Jacknife 校正) 來近似熵。如果使用 Jacknife 校正 (請參閱 [Beirlant2001]),則估計值為

\[n H(x) - (n - 1) \sum_{i = 1}^n H\left(x_{(i)}\right)\]

其中 \(n\) 是序列的長度,而 \(x_{(i)}\) 是刪除第 \(i\) 個元素的序列。

bucket_count (long) 決定直方圖桶子的數量。

x (double) 是樣本。

method (varchar) 為 'fixed_histogram_mle' (用於最大似然估計) 或 'fixed_histogram_jacknife' (用於經過 Jacknife 校正的最大似然估計)。

minmax (都是 double) 分別是最小值和最大值;如果輸入超出此範圍,函數會擲回例外狀況。

weight (double) 是樣本的權重,且必須為非負值。

例如,要使用 1000000 個 bin 和 jacknife 估計,找到 data 中權重為 1.0 且介於 0.01.0 之間的每個 x 的微分熵,請使用

SELECT
    differential_entropy(1000000, x, 1.0, 'fixed_histogram_jacknife', 0.0, 1.0)
FROM
    data

要使用 1000000 個桶子和最大似然估計,找到 data 中權重為 weight 且介於 -2.02.0 之間的每個 x 的微分熵,請使用

SELECT
    differential_entropy(1000000, x, weight, 'fixed_histogram_mle', -2.0, 2.0)
FROM
    data

注意

如果 \(x\) 沒有已知的下限和上限,建議使用採用 (sample_size, x) (未加權的情況) 或 (sample_size, x, weight) (加權的情況) 的版本,因為它們使用儲存庫取樣,這不需要樣本的已知範圍。

否則,如果相異權重的數量很少,特別是如果樣本數量很少,請考慮使用採用 (bucket_count, x, weight, "fixed_histogram_jacknife", min, max) 的版本,因為 jacknife 偏差校正比最大似然估計更好。但是,如果相異權重的數量很多,請考慮使用採用 (bucket_count, x, weight, "fixed_histogram_mle", min, max) 的版本,因為這會減少記憶體和執行時間。

approx_most_frequent(buckets, value, capacity) -> map<[same as value], bigint>()

計算最多 buckets 個元素的大約最常出現的值。函數的近似估計使我們能夠以更少的記憶體挑選出頻繁的值。較大的 capacity 可以提高基礎演算法的準確性,但會犧牲記憶體容量。傳回的值是一個對應表,其中包含最常出現的元素及其對應的估計頻率。

函數的錯誤取決於值的排列及其基數。我們可以將容量設定為與基礎資料的基數相同,以實現最小的錯誤。

bucketscapacity 必須是 bigint 型別。value 可以是數值或字串型別。

此函數使用 A.Metwally、D.Agrawal 和 A.Abbadi 在論文 Efficient computation of frequent and top-k elements in data streams 中提出的串流摘要資料結構。

水塘取樣函數

水塘取樣函數使用固定的樣本大小,與 TABLESAMPLE 相反。固定的樣本大小始終會產生固定的總大小,同時仍保證資料集中每個記錄都具有相同的被選取機率。請參閱 [Vitter1985]

reservoir_sample(initial_sample: array(T), initial_processed_count: bigint, values_to_sample: T, desired_sample_size: int) -> row(processed_count: bigint, sample: array(T))

根據給定的資訊計算新的水塘樣本

  • initial_sample:初始樣本陣列,若建立新的樣本則為 NULL

  • initial_processed_count:產生初始樣本陣列所處理的記錄數。如果 initital_sampleNULL,則應為 0 或 NULL

  • values_to_sample:要從中取樣的欄位。

  • desired_sample_size:水塘樣本的大小。

此函數輸出一個具有兩欄的單列型別

  1. 已處理計數:函數取樣的總列數。它包含來自 initial_processed_count 的總數 (如果有的話)。

  2. 水塘樣本:一個陣列,其長度相當於 desired_sample_sizevalues_to_sample 引數中數值的最小值。

WITH result as (
    SELECT
        reservoir_sample(NULL, 0, col, 5) as reservoir
    FROM (
        VALUES
        1, 2, 3, 4, 5, 6, 7, 8, 9, 0
    ) as t(col)
)
SELECT
    reservoir.processed_count, reservoir.sample
FROM result;
 processed_count |     sample
-----------------+-----------------
              10 | [1, 2, 8, 4, 5]

若要將較舊的樣本與新資料合併,請為 initial_sampleinitial_processed_count 引數提供有效的引數。

WITH initial_sample as (
    SELECT
        reservoir_sample(NULL, 0, col, 3) as reservoir
    FROM (
        VALUES
        0, 1, 2, 3, 4
    ) as t(col)
),
new_sample as (
    SELECT
        reservoir_sample(
            (SELECT reservoir.sample FROM initial_sample),
            (SELECT reservoir.processed_count FROM initial_sample),
            col,
            3
        ) as result
    FROM (
        VALUES
        5, 6, 7, 8, 9
    ) as t(col)
)
SELECT
    result.processed_count, result.sample
FROM new_sample;
 processed_count |  sample
-----------------+-----------
              10 | [8, 3, 2]

若要取樣表格的整個列,請使用 ROW 型別輸入,每個子欄位對應於來源表格的欄位。

WITH result as (
    SELECT
        reservoir_sample(NULL, 0, CAST(row(idx, val) AS row(idx int, val varchar)), 2) as reservoir
    FROM (
        VALUES
        (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')
    ) as t(idx, val)
)
SELECT
    reservoir.processed_count, reservoir.sample
FROM result;
 processed_count |              sample
-----------------+----------------------------------
               5 | [{idx=1, val=a}, {idx=5, val=e}]

雜訊聚合函數

請參閱 雜訊聚合函數


[Alizadeh2010] (1,2)

Alizadeh Noughabi, Hadi & Arghami, N. (2010). “A New Estimator of Entropy”.

[Beirlant2001]

Beirlant, Dudewicz, Gyorfi, and van der Meulen, “Nonparametric entropy estimation: an overview”, (2001)

[BenHaimTomTov2010]

Yael Ben-Haim and Elad Tom-Tov, “A streaming parallel decision tree algorithm”, J. Machine Learning Research 11 (2010), pp. 849–872.

[Black2015]

Black, Paul E. (26 January 2015). “Reservoir sampling”. Dictionary of Algorithms and Data Structures.

[Efraimidis2006]

Efraimidis, Pavlos S.; Spirakis, Paul G. (2006-03-16). “Weighted random sampling with a reservoir”. Information Processing Letters. 97 (5): 181–185.

[Vitter1985]

Vitter, Jeffrey S. “Random sampling with a reservoir.” ACM Transactions on Mathematical Software (TOMS) 11.1 (1985): 37-57.