私は2つのテーブルを持っています:
DATA
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
...
には約 20,000 行ありSAMPLES
ます。サンプルごとに、約 40,000 行ありDATA
ます。それぞれASSAY_ID
は、 のサンプルごとに 1 回だけ発生しDATA
ます。のサンプルのサブセットを取得し、 でグループ化して、SAMPLE
の各信号値の標準/Z スコア値を計算する必要があります。繰り返し呼び出されるストアド プロシージャを作成しようとしています。このストアド プロシージャは、定義済みのサンプル サブセット内のすべてのサンプルに対して単一の値と戻り値とペアを受け入れます。DATA
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 クエリを使用してこの計算を実行する最も効率的な方法は何ですか? 10 億行近くの行がDATA
あり、ほぼすべての値について Z スコアを計算する必要があることを考えると、実行時間が重要SIGNAL
です。
これまでに思いついた最高のクエリは次のとおりです。
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
このクエリを実行するより効率的な方法はありますか?
おまけの質問: 1 回の実行で EVERY に対してこの計算を実行する単一の SQL クエリを作成できますASSAY_ID
か?