L
o
a
d
i
n
g
.
.
.

ホーム

お知らせ

製品・ソリューション

サービス

導入事例・パートナー

EXEM Academy・ブログ

会社情報

採用情報

2022.06.22

SQL分析機能

Contents

  1. ANALYTIC FUNCTIONの理解
  2. ANALYTIC FUNCTIONの理解
  3. Window Aggregate Family
  4. FIRST/ LAST
  5. LAG/ LEAD
  6. ANALYTIC FUNCTIONの実行。
  7. ROLLUP/ CUBE

Analytic Functionとは?

・Business 分野で頻繁に行われる様々な形態の分析に有用に活用できる

SQL Function

・Running Summary, Moving Average, Ranking, Row 比較(LEAD/LAG Func)

・Pointer/Offsetの概念が導入

・Query Speed の向上

・改善された開発生産性

・Self Joinなどにより困難に実装されたSQLをより容易に表現可能

・大量のデータで複数のAnalytic Functionを使用すると、パフォーマンスの低下が発生する可能性があります。

・Oracle 8iからのサポート

分析機能の実行プロセス

  1. General Query Processing :  JoinWhere条件節、Group ByHavingなどの既存のQuery Processing実行ステップ。
  2. Analytic Function Applying :ステップ1の結果を持つ実際のAnalytic Functionが適用され、必要計算を行うステップ。

⇒つまり、Analytic Functionの実行対象はSELECT句の列です。

3.Order By Processing :  QueryにOrder By句がある場合は、最終結果のOrdering実行ステップ。

SELECT ename, sal, job,

RANK()   OVER ( PARTITION BY job ORDER BY sal ) rank_sal, SUM(sal) OVER ( PARTITION BY job ORDER BY sal ) sum_sal

FROM emp WHERE sal > 100 ORDER BY job

分析機能のメカニズム

  1. Partitioning

– PARTITION BY句の列構成によるパーティションの設定。

– PARTITION BY句未記述の場合、全体を1つのパーティションとして扱います。

2.Ordering

– ORDER BY 句 記述時にパーティション単位で ORDER BY 句列の順序でソートします。

ORDER BY句は、Analytic Functionの種類(特性)別にのみ記述可能。

⇒ORDERINGが必要ない場合は省略可能!

3.Caculations Based on Window Contents

設定された処理範囲のターゲットROWに対してAnalytic Functionを実行。

4.Analytic FunctionはSELECT句とORDER BY句にのみ対応することができます。

5.Analytic Functionを適用した後のQueryの結果集合レベルは、Analytic Functionを適用する前の

結果セットレベルと同じ(Grouping Setを除く)

6.PGAのSORT_AREA_SIZEとTemporary Segmentの使用。

ResultSet,Window,CurrentRow

分析機能リスト(9iR2ベース)

目的:結果セット内の他のレコードと比較してランク付けするために使用

Syntax : RANK() OVER ( [PARTITION BY <value expression1> [, …]]

ORDER BY <value expression2> [collate clause] [ASC|DESC] [NULLS FIRST|NULLS LAST] [, …] )

  • RANK and DENSE_RANK
  • CUME_DIST and PERCENT_RANK
  • NTILE
  • ROW_NUMBER

Sample

SELECT ename,job,sal,

RANK()      OVER (PARTITION BY job ORDER BY sal) Rank1   ,

DENSE_RANK() OVER (PARTITION BY job ORDER BY sal) Dense_Rank                                             ,

ROW_NUMBER() OVER (PARTITION BY job ORDER BY sal) Rownum_Rank FROM   emp

WHERE  job IN (‘CLERK’, ‘SALESMAN’);

ENAMEJOBSALRANK1DENSE_RANKROWNUM_RANK
SMITHCLERK800111
JAMESCLERK950222
ADAMSCLERK1100333
MILLERCLERK1300444
MARTINSALESMAN1250111
WARDSALESMAN1250112
TURNERSALESMAN1500323
ALLENSALESMAN1600434

目的: Aggregate Functionの拡張形式

Syntax : {SUM|AVG|MAX|MIN|COUNT|STDDEV|VARIANCE|FIRST_VALUE|LAST_VALUE}

({<value expression1> | *})

OVER ([PARTITION BY <value expression2>[,…]]

ORDER BY <value expression3>[collate clause>][ASC| DESC] [NULLS FIRST | NULLS LAST] [,…]

ROWS | RANGE{ {UNBOUNDED PRECEDING |

<value expression4> PRECEDING}|

BETWEEN {UNBOUNDED PRECEDING |

<value expression4> PRECEDING} AND {CURRENT ROW |

<value expression4> FOLLOWING} }

)

Window Size定義で使用されるKEY WORD

q ROWS                                     : 物理的なROW単位でWINDOWを指定することを示します。

q RANGE                                    : 論理的な相手先としてWINDOWを指定することを示します。

  • CURRENT ROW                     : 現在の Row で Window が開始または終了することを示します。
  • UNBOUNDED PRECEDING : Partitionの最初の行でWindowが開始されることを示します。
  • UNBOUNDED FOLLOWING : Partition の最後の行で Window が終了したことを示します。
  • Order By句がない場合      : RANGE BETWEEN UNBOUNDED PRECEDING

AND UNBOUNDED FOLLOWING

  • Order By句がある場合      : RANGE BETWEEN UNBOUNDED PRECEDING

AND CURRENT ROW       

Range のない Analytic Function

SELECT ename,job,

SUM(sal) OVER (PARTITION BY job ORDER BY empno) nujuk_sum , SUM(sal)        OVER (PARTITION BY job)                p_sum     ,

SUM(sal)        OVER ()                   all_sum , FIRST_VALUE(sal) OVER (PARTITION BY job ORDER BY empno) first_value, LAST_VALUE(sal) OVER (PARTITION BY job ORDER BY empno) last_value

FROM emp

WHERE job IN (‘CLERK’, ‘MANAGER’);

ENAMEJOBNUJUK_SP_SUMALL_SUMFIRST_VLAST_VALUE
SMITHCLERK800515013425800800
ADAMSCLERK19005150134258001100
JAMESCLERK2850515013425800950
MILLERCLERK41505150134258001300
JACKCLERK51505150134258001000
JONESMANAGER297582751342529752975
BLAKEMANAGER582582751342529752850
CLARKMANAGER827582751342529752450

NumberTypeのRange

       
ENAMEJOBSALROWNUMSAL1SAL2SAL3
JAMESCLERK95019509501750
SMITHCLERK8002175017502850
ADAMSCLERK11003190019003200
MILLERCLERK13004240024003400
JACKCLERK10005230023002300

DateTypeのRange

SELECT ename,job, sal, TRUNC(hiredate),

SUM(sal) OVER (PARTITION BY job ORDER BY hiredate ROWS 1 PRECEDING                                              ) rows_1 ,

SUM(sal) OVER (PARTITION BY job ORDER BY hiredate

RANGE BETWEEN INTERVAL                    ‘1’ YEAR PRECEDING

AND INTERVAL          ‘1’ YEAR FOLLOWING ) year_1 ,

SUM(sal) OVER (PARTITION BY job ORDER BY hiredate

RANGE BETWEEN INTERVAL                    ‘1’ MONTH PRECEDING

AND INTERVAL          ‘2’ MONTH FOLLOWING) month_1,

SUM(sal) OVER (PARTITION BY job ORDER BY hiredate

RANGE BETWEEN INTERVAL                    ‘1’ DAY PRECEDING

AND INTERVAL ’99’ DAY FOLLOWING            ) day_1

FROM emp

WHERE job = ‘CLERK’

ORDER BY hiredate;

ENAMEJOBSALHIREDATEROWSYEARMONTHDAY_1
JACKCLERK10001980/12/011000180018001800
SMITHCLERK8001980/12/17180027501800800
JAMESCLERK9501981/12/031750305022502250
MILLERCLERK13001982/01/232250335013001300
ADAMSCLERK11001983/01/122400240011001100

VariableTypeのRange

SELECT a.ename,a.job, a.sal,rownum,b.no1,

SUM(sal) OVER (PARTITION BY job ORDER BY rownum RANGE BETWEEN b.no1 PRECEDING

AND b.no1 FOLLOWING ) sal3

FROM emp a,

( SELECT 1 no1 FROM dual

UNION ALL

SELECT 2 no1 FROM dual

) b

WHERE job = ‘CLERK’;

ENAMEJOBSALROWNUMNO1SAL3
JAMESCLERK950111900
JAMESCLERK950223500
SMITHCLERK800312550
SMITHCLERK800424750
ADAMSCLERK1100513000
ADAMSCLERK1100625600
MILLERCLERK1300713700
MILLERCLERK1300825700
JACKCLERK1000913300
JACKCLERK10001023300

目的: ORDER BY句で指定された最初または最後の値を見つけるために使用されます。

Syntax : {MIN | MAX | SUM | AVG | COUNT | VARIANCE | SETDEV }

KEEP ( DENS_RANK FIRST ORDER BY <value expression1>

[ASC | DESC] [NULL FIRST| NULL LAST]

OVER ([PARTITION BY <value expression2>[,…]] )

  •  一般的なAnalytic Function
  • 各パーティションにグループ関数を適用します。
  • FIRST/LAST

各パーティションごとの基準項目でソートした後、FIRST / LAST Value Setにグループ関数を適用します。

SELECT empno,, deptno, sal , hiredate,

min(hiredate) OVER (partition by deptno order by sal) nor_min , min(hiredate) OVER (partition by deptno                        ) nor2_min , min(hiredate) KEEP (DENSE_RANK FIRST ORDER BY       )

OVER (partition by deptno                              ) first_min

FROM scott.emp

EMPNODEPTNOSALHIREDATENOR_MINNOR2_MINFIRST_MIN
79341013001982-01-231982-01-231981-06-091982-01-23
77821024501981-06-091981-06-091981-06-091982-01-23
78391050001981-11-171981-06-091981-06-091982-01-23
7369208001980-12-171980-12-171980-12-171980-12-17
78762011001983-01-121980-12-171980-12-171980-12-17
75662029751981-04-021980-12-171980-12-171980-12-17
77882030001982-12-091980-12-171980-12-171980-12-17

目的:テブルの2行を位置にじて比較するために使用します。

Syntax : {LAG | LEAD}(<value expression1>, [<offset> [, <default>]]) OVER ([PARTITION BY <value expression2>[,…]]

ORDER BY <value expression3> [collate clause>][ASC | DESC]

[NULLS FIRST | NULLS LAST] [,…]

)

  • LAG     以前のROW比較
  • LEAD 以降のROW比較

– RDBMSの基本原則に違反しますが、前後のロー比較はSQL作成効率を向上させる強力な機能を提供。

à Self Join、レプリケーションでしか処理できなかった既存の方式を改善。

( RDBMSの論理上の集合内のすべての行間の物理的、論理的関連性はありません!)

SELECT empno, job,

TO_CHAR(hiredate,’yyyymmdd’) hiredate,

LAG(hiredate) OVER (PARTITION BY job ORDER BY hiredate) lag_1 , LEAD(hiredate) OVER (PARTITION BY job ORDER BY hiredate) lead_1 , LAG(hiredate,2) OVER (PARTITION BY job ORDER BY hiredate) lag_2 , LEAD(hiredate,2) OVER (PARTITION BY job ORDER BY hiredate) lead_2

FROM   emp

WHERE  job IN (‘CLERK’, ‘SALESMAN’) ;

EMPNOJOBHIREDATELAG_1LEAD_1LAG_2LEAD_2
9999CLERK19801201 1980/12/17 1981/12/03
7369CLERK198012171980/12/011981/12/03 1982/01/23
7900CLERK198112031980/12/171982/01/231980/12/011983/01/12
7934CLERK198201231981/12/031983/01/121980/12/17 
7876CLERK198301121982/01/23 1981/12/03 
7499SALESMAN19810220 1981/02/22 1981/09/08
7521SALESMAN198102221981/02/201981/09/08 1981/09/28
7844SALESMAN198109081981/02/221981/09/281981/02/20 
7654SALESMAN198109281981/09/08 1981/02/22 

Lag / Leadを使用して冗長履歴を分割する

SELECT  ban,s_date,e_date FROM test ;

BANS_DATEE_DATE
A199807199809
B199805199807

Data複製を介して線分を作成する

SELECT ban,DECODE(no1,1,s_date,e_date) from_dt

FROM test, ( SELECT 1 no1 FROM dual

UNION ALL

SELECT 2 no1 FROM dual ) GROUP BY ban, DECODE(no1,1,s_date,e_date);

Lag/Leadを使用して線分を作成する

SELECT ban, from_dt,

LEAD(from_dt) OVER (PARTITION BY ban ORDER BY from_dt) to_dt FROM ( SELECT ban, DECODE(no1, 1, s_date, e_date) from_dt

FROM test,

( SELECT 1 no1

FROM dual UNION ALL SELECT 2 no1

FROM dual )

GROUP BY ban, DECODE(no1, 1, s_date, e_date)

)

元の線分と新しく作成した線分とBetweenJoin

SELECT b.ban,b.from_dt,b.to_dt FROM test a,

( SELECT ban,  from_dt,

LEAD(from_dt) over ( PARTITION BY ban

ORDER BY from_dt) to_dt

FROM ( SELECT ban,

DECODE(no1, 1, s_date, e_date) from_dt FROM test,

( SELECT 1 no1

FROM dual UNION ALL SELECT 2 no1

FROM dual )

GROUP BY ban, DECODE(no1, 1, s_date, e_date)

)

) b

WHERE  a.ban     = b.ban

AND    b.from_dt < a.e_date

AND b.to_dt > a.s_date GROUP BY b.ban,b.from_dt,b.to_dt HAVING COUNT(*) > 2 ;

Analytic Function 実行計画

SELECT OWNER, OBJECT_NAME,

COUNT(*) OVER (PARTITION BY OWNER,TEMPORARY ) OBJTYPE_CNT , COUNT(*)   OVER (PARTITION BY TEMPORARY   )  TEMP_CNT   , COUNT(*) OVER (PARTITION BY OBJECT_TYPE ) TYPE_CNT  , ROW_NUMBER() OVER (PARTITION BY OWNER, OBJECT_TYPE

ORDER BY OBJECT_NAME                      )           OBJTYPE_POS ,

COUNT(*) OVER ( )                                       TOT_CNT

FROM BIG_OBJECTS WHERE OWNER = ‘HR’

*********************************************************************************************

SELECT STATEMENT CHOOSE-Cost : 6

WINDOW SORT WINDOW SORT

TABLE ACCESS BY INDEX ROWID FIRE.BIG_OBJECTS(1)

INDEX RANGE SCAN FIRE.BIG_OBJECTS_IDX2(U) (OWNER,OBJECT_NAME,SUBOBJECT_NAME,OBJECT_TYPE)

□実行計画上の表示

– Analytic FunctionはGeneral Result Setで処理されます。 実行計画上ではWINDOW SORTと表示されます。

WINDOW SORTは、記述されたAnalytic FunctionのPARTITION BY句の列構成に従って決定されます。

PARTITION BY句の先頭列からの構成順序、または結合によって決定されます

作成ガイド

– PARTITION BY句の構成順序が一致する順序で記述。

□   RollupはGROUP BYの拡張形式(小計、合計形式)

□  Cube は、複製テーブルと同じ役割をする Cube を生成し、結合可能なすべての値に対して

SUBTOTALを生成する

□Parallelで実行可能

□    時間や地域など、階層分類(大分類、中分類、小分類)を含むデータの集計に適しています。

□    Copy_Tのように複製テーブルを作成する必要はなく、Performanceの観点からもプラス

□    過度に多くの Column を Cube に割り当てると、システムのリソースを過剰に使用する

□ GROUPING関数の導入(Rollup、Cubeでのみ使用するNULL判定)- 元データの行と列とSub Totalの区別のために使用。

SubTotalを作成

Rollupの SUBTOTAL

GROUPING COLUMNSの数(n) n+1 LEVELのSUBTOTALを生成する

Cubeの SUBTOTOAL

GROUPING COLUMNSの数(n) n2 LEVELSUBTOTAL生成

GROUPING関数: ROLLUPORCUBEにより、 生成されたNullvalueに出会ったら数字1を返します。  

SELECT DECODE(GROUPING(dname), 1, ‘All Departments’,dname) dname , DECODE(GROUPING(job) , 1, ‘All Jobs’, job)  job  , COUNT(*) total_cnt,

SUM(sal) amt , GROUPING(dname) g1, GROUPING(job) g2

FROM emp a, dept b WHERE a.deptno = b.deptno

GROUP BY ROLLUP (dname, job);

原集合を保存しながらSub TotalとGrand Totalを入手する

SELECT b.deptno ,b.dname,sal FROM emp a, dept b

WHERE a.deptno = b.deptno AND a.deptno IN (10,20)

DEPTNODNAMESAL
10ACCOUNTING5500
10ACCOUNTING2450
10ACCOUNTING1300
10ACCOUNTING      total amount9250
20RESEARCH2975
20RESEARCH3000
20RESEARCH800
20RESEARCH3000
20RESEARCH1100
20RESEARCH       total amount10875
 Final total amount20125

原集合を保存しながらSub TotalとGrand Totalを入手する

SELECT b.deptno ,

DECODE(ROWNUM || b.deptno, null,’ Final total amount’,

b.deptno, MIN(b.dname)||’ total amount’, MIN(b.dname)             ) dname ,

SUM(a.sal) sal

FROM emp a, dept b

WHERE a.deptno = b.deptno

GROUP BY ROLLUP( b.deptno,ROWNUM )

SELECT DECODE(GROUPING(dname), 1, ‘~All Dept’,dname) AS dname, DECODE(GROUPING(job) , 1, ‘~All Jobs’, job ) AS job , COUNT(*) “Total”, SUM(sal) “amount”,

GROUPING(dname) G1,GROUPING(job) G2

FROM emp a, dept b

WHERE a.deptno = b.deptno AND a.deptno in (10,20)

GROUP BY CUBE (dname, job) ORDER BY dname ,job ;


PHP Code Snippets Powered By : XYZScripts.com