2

基本的に、ジョブ バッチのリスト、各バッチに含まれるジョブの数、および各ジョブ バッチの期間で構成されるデータセットがあります。サンプル データセットを次に示します。

CREATE TABLE test_data
(
   batch_id    NUMBER,
   job_count   NUMBER,
   duration    NUMBER
);

INSERT INTO test_data VALUES (1, 37, 9);
INSERT INTO test_data VALUES (2, 47, 4);
INSERT INTO test_data VALUES (3, 66, 6);
INSERT INTO test_data VALUES (4, 46, 6);
INSERT INTO test_data VALUES (5, 54, 1);
INSERT INTO test_data VALUES (6, 35, 1);
INSERT INTO test_data VALUES (7, 55, 9);
INSERT INTO test_data VALUES (8, 82, 7);
INSERT INTO test_data VALUES (9, 12, 9);
INSERT INTO test_data VALUES (10, 52, 4);
INSERT INTO test_data VALUES (11, 3, 9);
INSERT INTO test_data VALUES (12, 90, 2);

ここで、期間フィールドのパーセンタイルを計算したいと思います。通常、これは次のような方法で行われます。

SELECT
       PERCENTILE_DISC( 0.75 )
          WITHIN GROUP (ORDER BY duration ASC)
          AS third_quartile
FROM
       test_data;

(結果は 9 になります)

ここでの問題は、バッチに基づいてパーセンタイルを取得したくないことです。個々のジョブに基づいてパーセンタイルを取得したいのです。これは、job_count の現在の合計を生成することで、非常に簡単に手で把握できます。

SELECT
       batch_id,
       job_count,
       SUM(
            job_count
       )
       OVER (
              ORDER BY duration
              ROWS UNBOUNDED PRECEDING
             )
          AS total_jobs,
        duration
FROM
       test_data
ORDER BY
       duration ASC;

BATCH_ID     JOB_COUNT    TOTAL_JOBS   DURATION     
6            35           35           1            
5            54           89           1            
12           90           179          2            
2            47           226          4            
10           52           278          4            
3            66           344          6            
4            46           390          6            
8            82           472          7            
9            12           484          9            
1            37           521          9            
11           3            524          9            
7            55           579          9           

579 個のジョブがあるため、75 パーセンタイルはジョブ 434 になります。上記の結果セットを見ると、これは 7 の期間に対応しており、標準関数の動作とは異なります。

基本的に、バッチ内の各ジョブを個別の観察と見なし、バッチではなく、それらに基づいてパーセンタイルを決定したいと考えています。

これを達成するための比較的簡単な方法はありますか?

4

2 に答える 2

3

これを「加重」パーセンタイルと考えます。Oracleにこれに対する組み込みの分析関数があるかどうかはわかりませんが、計算するのは簡単です。そして、あなたはそこに向かっています。

追加のアイデアは、ジョブの総数を計算し、算術演算を使用して必要な値を選択することです。75 パーセンタイルの場合、値は、ジョブの累積数がジョブの総数の 0.75 倍を超える最小期間です。

SQL での例を次に示します。

select pcs.percentile, min(case when cumjobs >= totjobs * percentile then duration end)
from (SELECT batch_id, job_count,
             SUM(job_count) OVER (ORDER BY duration) as cumjobs,
             sum(job_count) over () as totjobs,
             duration
      FROM test_data
     ) t cross join
     (select 0.25 as percentile from dual union all
      select 0.5 from dual union all
      select 0.75 from dual
     ) pcs
group by pcs.percentile;

この例では、パーセンタイル値 (および追加のボーナスとして、3 つの異なるパーセンタイル) と、各値がそれぞれの行に表示されます。各行の値が必要な場合は、元のテーブルに結合する必要があります。

于 2013-05-08T23:51:43.737 に答える
0

わかった。私はあなたの答えを持っていると思います。アイデアは私のものです。実装はこの Ask Tom の記事から借用しています

SELECT PERCENTILE_DISC( 0.75 )
       WITHIN GROUP (ORDER BY duration ASC)
       AS third_quartile
FROM(
with data as
  (select level l
   from dual, (select max(job_count) max_jobs from test_data)
   connect by level <= max_jobs
  )
  select *
  from test_data, data
  where l <= job_count
  --ORDER BY duration, batch_id
  ) inner
;

これがSQL Fiddleです。

于 2013-05-08T23:56:39.503 に答える