的Z值我有兩個表: DATA
的Oracle SQL:最有效的方法來計算分組數據
DATA_ID | SAMPLE_ID | ASSAY_ID | SIGNAL
101 | 201 | 301 | 2.87964
102 | 201 | 302 | 7.64623
103 | 202 | 301 | 1.98473
...
而且SAMPLES
:
SAMPLE_ID | SAMPLE_NAME | CATEGORY
201 | SAMP0001 | CAT A
202 | SAMP0002 | CAT B
203 | SAMP0003 | CAT A
...
有在SAMPLES
約20000行。對於每個樣品,DATA
中有大約40,000行。 DATA
中的每個樣本每個ASSAY_ID
恰好出現一次。我需要在SAMPLE
中抽取一部分樣本,並計算DATA
中每個信號值的標準/ z分數值,按ASSAY_ID
分組。我正在嘗試創建一個將被重複調用的存儲過程,該過程將接受一個ASSAY_ID
值,並返回SAMPLE_ID
和ZSCORE
對,用於預定義採樣子集中的所有采樣。
給定一組樣品信號值(X = [3.21, 4.56, 1.12, ..]
)對於給定的測定中,在這種情況下,標準/ z得分被計算爲
(X[i] - median(X))/(K * MAD)
凡K
是一個比例因子等於1.4826和MAD是中值調整後的偏差等於:
median(|X[i]-median(X)|)
明白了嗎?好:)現在,使用SQL查詢執行此計算的最有效方法是什麼?執行時間很關鍵,因爲DATA
中有近10億行,並且幾乎每個SIGNAL
值都需要計算z分數。
這裏是我已經能夠拿出迄今最佳的查詢:
WITH BASE AS (
SELECT
S.SAMPLE_ID,
D.SIGNAL
FROM
DATA D
JOIN SAMPLES S
ON D.SAMPLE_ID = S.SAMPLE_ID
WHERE
S.CATEGORY IN ('CAT A', 'CAT B')
AND D.ASSAY_ID = 12345
AND S.SAMPLE_NAME NOT IN ('SAMP0003', 'SAMP0005', 'SAMP0008')
)
SELECT
A.SAMPLE_ID,
(A.SIGNAL-B.MED)/(1.4826*C.MAD) AS ZSCORE
FROM
BASE A,
(
SELECT MEDIAN(X.SIGNAL) AS MED
FROM BASE X
) B,
(
SELECT MEDIAN(ABS(Y.SIGNAL-YY.MED)) AS MAD
FROM BASE Y,
(SELECT MEDIAN(SIGNAL) AS MED FROM BASE) YY
) C
是否有執行該查詢更有效的方式?
獎勵題:我可以寫一個SQL查詢,將在單個執行執行此計算爲每ASSAY_ID
?
謝謝,當我明天上班時,我會試試這個!假設這更快,爲什麼會這樣? – woemler
沒有適當的數據我猜測了很多,但它看起來像'WITH'方法實現基本查詢到一個臨時表中,可以完全掃描四次。分析函數方法似乎可以通過對錶DATA的單次完整掃描而消除。 –
一些快速測試表明此版本的查詢速度稍快,並且查詢計劃顯示成本略有下降。同樣重要的是,這是更簡潔的代碼和獎勵問題的一個很好的答案。謝謝! – woemler