1.排名函數:
RANK and DENSE_RANK Functions
語法如下:
RANK ( ) OVER ( [query_partition_clause] order_by_clause )
DENSE_RANK ( ) OVER ( [query_partition_clause]order_by_clause )
在排名函數中order by是不可選字段,表示你要按什麼進行排名,partition是可選字段,如果沒有partition則表示對全部數據進行排名,如果有partition則表示在分區內進行排序。
我們先來看一個例子:
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(SAL) SAL,
4 RANK() OVER(ORDER BY SUM(SAL) DESC)RANK_DESC,
5 RANK() OVER(ORDER BY SUM(SAL))RANK_ASC,
6 DENSE_RANK() OVER(ORDER BY SUM(SAL)DESC) DENSE
7 FROM EMP
8 GROUP BY DEPTNO, EMPNO;
EMPNO DEPTNO SAL RANK_DESC RANK_ASC DENSE
---------- ---------- ---------- ---------- --------------------
7900 30 950 14 1 12
7876 20 1100 13 2 11
7521 30 1250 11 3 10
7654 30 1250 11 3 10
7934 10 1300 10 5 9
7844 30 1500 9 6 8
7499 30 1600 8 7 7
7782 10 2450 7 8 6
7698 30 2850 6 9 5
7566 20 2975 5 10 4
7902 20 3000 3 11 3
EMPNO DEPTNO SAL RANK_DESC RANK_ASC DENSE
---------- ---------- ---------- ---------- --------------------
7788 20 3000 3 11 3
7839 10 5000 2 13 2
7369 20 10000 1 14 1
已選擇14行。
在以上這個例子中我們可以看到,oracle默認是按照asc進行排名的,rank函數的排名是有間隙的,比如說上面兩個11名,接下來就是13名,而dense_rank是沒有間隙的。
接下來看一下partition是如何處理的
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(SAL) SAL,
4 RANK() OVER(PARTITION BY deptno ORDERBY SUM(SAL) DESC) rank_par
5 FROM EMP
6 GROUP BY DEPTNO, EMPNO;
EMPNO DEPTNO SAL RANK_PAR
---------- ---------- ---------- ----------
7839 10 5000 1
7782 10 2450 2
7934 10 1300 3
7369 20 10000 1
7788 20 3000 2
7902 20 3000 2
7566 20 2975 4
7876 20 1100 5
7698 30 2850 1
7499 30 1600 2
7844 30 1500 3
EMPNO DEPTNO SAL RANK_PAR
---------- ---------- ---------- ----------
7521 30 1250 4
7654 30 1250 4
7900 30 950 6
已選擇14行。
可以看到oracle在deptno內進行了排序,也就是以deptno爲分區進行排序。
NTILEFunction
語法如下:
NTILE (expr) OVER([query_partition_clause] order_by_clause)
ntile函數會按照order by對數據進行切片,但是有一個比較有趣的情況,那就是當數據不能平分時,Oracle會將不能平分的數據按照片號從高到低一個一個的分配,例子如下:
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(SAL) SAL,
4 ntile(4) OVER(ORDER BY SUM(SAL) DESC)til
5 FROM EMP
6 GROUP BY DEPTNO,EMPNO;
EMPNO DEPTNO SAL TILE
---------- ---------- ---------- ----------
7369 20 10000 1
7839 10 5000 1
7788 20 3000 1
7902 20 3000 1
7566 20 2975 2
7698 30 2850 2
7782 10 2450 2
7499 30 1600 2
7844 30 1500 3
7934 10 1300 3
7654 30 1250 3
EMPNO DEPTNO SAL TILE
---------- ---------- ---------- ----------
7521 30 1250 4
7876 20 1100 4
7900 30 950 4
ROW_NUMBERFunction
ROW_NUMBER ( ) OVER ([query_partition_clause] order_by_clause )
這個函數會根據order by對每一行分配一個特定的編號,從1開始。例子如下:
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(SAL) SAL,
4 row_number() OVER(ORDER BY SUM(SAL)DESC) row_number
5 FROM EMP
6 GROUP BY DEPTNO,EMPNO;
EMPNO DEPTNO SAL ROW_NUMBER
---------- ---------- ---------- ----------
7369 20 10000 1
7839 10 5000 2
7788 20 3000 3
7902 20 3000 4
7566 20 2975 5
7698 30 2850 6
7782 10 2450 7
7499 30 1600 8
7844 30 1500 9
7934 10 1300 10
7654 30 1250 11
EMPNO DEPTNO SAL ROW_NUMBER
---------- ---------- ---------- ----------
7521 30 1250 12
7876 20 1100 13
7900 30 950 14
其它一些函數並不常用,請參照官方文檔。
2.window函數
先來看看Oracle官方文檔的介紹吧
Windowing functions can be used to computecumulative, moving, and centered aggregates. They return a value for each rowin the table, which depends on other rows in the corresponding window. Withwindowing aggregate functions, you can calculate moving andcumulative versions of SUM, AVERAGE, COUNT, MAX,MIN, andmany more functions. They can be used only inthe SELECT and ORDER BY clauses of the query.Windowing aggregate functions include the convenientFIRST_VALUE, which returnsthe first value in the window; and LAST_VALUE, which returns the lastvalue in the window. These functions provide access to more than one row of atable without a self-join.
語法如下:
analytic_function([arguments ])
OVER (analytic_clause)
where analytic_clause=
[ query_partition_clause ]
[ order_by_clause [ windowing_clause] ]
andquery_partition_clause =
PARTITION BY
{ value_expr[, value_expr ]...
}
and windowing_clause =
{ ROWS | RANGE }
{ BETWEEN
{ UNBOUNDED PRECEDING
| CURRENT ROW
| value_expr { PRECEDING | FOLLOWING}
}
AND
{ UNBOUNDED FOLLOWING
| CURRENT ROW
| value_expr { PRECEDING | FOLLOWING}
}
| { UNBOUNDED PRECEDING
| CURRENT ROW
| value_expr PRECEDING
}
}
在瞭解之前先了解一下rows和range的區別,
rows表示一個物理窗口,也就是排序後,按排序結果的行號對應確定窗口
Range是默認窗口,表示一個行和行之間的邏輯關係(當前行的排序鍵的value加或減邏輯偏移量得到當前行對應的邏輯窗口的範圍)
Cumulative Aggregate Function
下面這個例子表示對一個部門的工資進行累加
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(sal),
4 SUM(SAL) OVER(
5 PARTITION BY deptno ORDER BY empno DESCROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
6 ) row_number
7 FROM EMP
8 GROUP BY DEPTNO,EMPNO,sal;
EMPNO DEPTNO SUM(SAL) ROW_NUMBER
---------- -------------------- ----------
7934 10 1300 1300
7839 10 5000 6300
7782 10 2450 8750
7902 20 3000 3000
7876 20 1100 4100
7788 20 3000 7100
7566 20 2975 10075
7369 20 10000 20075
7900 30 950 950
7844 30 1500 2450
7698 30 2850 5300
EMPNO DEPTNO SUM(SAL) ROW_NUMBER
---------- -------------------- ----------
7654 30 1250 6550
7521 30 1250 7800
7499 30 1600 9400
這個例子中,窗口開始於partition by的第一條數據,結束於當前行,oracle默認的結束爲currentrow
MovingAggregate Function
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(sal),
4 SUM(SAL) OVER(
5 PARTITION BY deptno ORDER BY empno DESC ROWS BETWEEN 1 PRECEDING AND 1Following
6 ) rows_sum
7 FROMEMP
8 GROUP BY DEPTNO,EMPNO,sal;
EMPNO DEPTNO SUM(SAL) ROWS_SUM
---------- -------------------- ----------
7934 10 1300 6300 --這個表示1 PRECEDING,就是向前推進一行
7839 10 5000 8750 --假如這個是當前行
7782 10 2450 7450 --這個表示1 Following,就是向後推進一行
7902 20 3000 4100
7876 20 1100 7100
7788 20 3000 7075
7566 20 2975 15975
7369 20 10000 12975
7900 30 950 2450
7844 30 1500 5300
7698 30 2850 5600
EMPNO DEPTNO SUM(SAL) ROWS_SUM
---------- ---------- --------------------
7654 30 1250 5350
7521 30 1250 4100
7499 30 1600 2850
下面我們來看range是怎麼樣進行偏移的。
CenteredAggregate Function
SQL> SELECT EMPNO,
2 DEPTNO,
3 SUM(SAL),
4 SUM(SAL) OVER(PARTITION BY DEPTNO ORDER BY SAL DESC RANGE BETWEEN 10
0 PRECEDING AND 300FOLLOWING) ROWS_SUM
5 FROM EMP
6 GROUP BY DEPTNO, EMPNO, SAL;
EMPNO DEPTNO SUM(SAL) ROWS_SUM
---------- ---------- --------------------
7839 10 5000 5000
7782 10 2450 2450
7934 10 1300 1300
7369 20 10000 10000
7788 20 3000 8975
7902 20 3000 8975
7566 20 2975 8975
7876 20 1100 1100
7698 30 2850 2850
7499 30 1600 3100 ----開始處
7844 30 1500 5600 --假如這個是當前行,那麼上面就表示的範圍是1500-300=1200 1600之間
EMPNO DEPTNO SUM(SAL) ROWS_SUM
---------- -------------------- ----------
7521 30 1250 3450
7654 30 1250 3450--結束處
7900 30 950 950
升序range窗口preceding含義是比當前行小xx值,following含義是比當前行大xx值,降序range窗口preceding含義是比當前行大xx值,following含義是比當前行小xx值。
3.Reporting函數
語法如下:
{SUM |AVG | MAX | MIN | COUNT | STDDEV | VARIANCE ... }
([ALL | DISTINCT] {value expression1[,...] | *})
OVER ([PARTITION BY valueexpression2[,...]])
這個比較簡單不在用實例說明了。
RATIO_TO_REPORTFunction
語法如下:RATIO_TO_REPORT( expr ) OVER ( [query_partition_clause] )
這個函數表示expr這個值在expr所在字段和中所佔的比例,實例如下:
SQL> SELECT DEPTNO,
2 EMPNO,
3 SUM(SAL) SAL,
4 SUM(SAL) OVER() TOTAL,
5 to_char(RATIO_TO_REPORT(SUM(sal))OVER(),'9990.99') RATIO
6 FROM EMP
7 GROUP BY DEPTNO, EMPNO,sal;
DEPTNO EMPNO SAL TOTAL RATIO
---------- ---------- ---------- ---------- --------
30 7499 1600 38225 0.04 --1600/38225
20 7566 2975 38225 0.08
20 7788 3000 38225 0.08
10 7839 5000 38225 0.13
20 7876 1100 38225 0.03
20 7369 10000 38225 0.26
30 7654 1250 38225 0.03
30 7521 1250 38225 0.03
20 7902 3000 38225 0.08
10 7782 2450 38225 0.06
10 7934 1300 38225 0.03
DEPTNO EMPNO SAL TOTAL RATIO
---------- ---------- ---------- ---------- --------
30 7698 2850 38225 0.07
30 7844 1500 38225 0.04
30 7900 950 38225 0.02
4.LAG/LEAD
語法如下:
{LAG | LEAD} (value_expr [, offset] [, default] ) [RESPECT NULLS|IGNORE NULLS]
OVER ( [query_partition_clause] order_by_clause)
Offset 表示偏移量,當指定ignore nulls在發生偏移時oracle會忽略null。
例子如下:
SQL> SELECT DEPTNO,
2 empno,
3 sal,
4 LAG(sal,1) OVER(ORDER BY EMPNO DESC)LA,
5 LEAD(SAL,1) OVER(ORDER BY EMPNO DESC)LE
6 FROM EMP
7 GROUP BY DEPTNO,empno,sal;
DEPTNO EMPNO SAL LA LE
---------- ---------- ---------- ---------- ----------
10 7934 1300 3000
20 7902 3000 1300 950
30 7900 950 3000 1100
20 7876 1100 950 1500
30 7844 1500 1100 5000
10 7839 5000 1500 3000
20 7788 3000 5000 2450
10 7782 2450 3000 2850
30 7698 2850 2450 1250
30 7654 1250 2850 2975
20 7566 2975 1250 1250
DEPTNO EMPNO SAL LA LE
---------- ---------- ---------- ---------- ----------
30 7521 1250 2975 1600
30 7499 1600 1250 10000
20 7369 10000 1600
5.FIRST_VALUEand LAST_VALUE Functions
語法如下:
FIRST_VALUE|LAST_VALUE( <expr> ) [RESPECT NULLS|IGNORE NULLS] OVER (analytic clause );
這個函數用來返回窗口的第一個值或者最後一個值,但是這個有一個有趣的例子,我們來看看
先來看一個例子:
SQL> SELECT DEPTNO,
2 EMPNO,
3 sal,
4 FIRST_VALUE(SAL) OVER(PARTITION BYDEPTNO ORDER BY EMPNO ROWS betwee
n unbounded preceding and current row) FIRST,
5 LAST_VALUE(SAL) OVER(PARTITION BYDEPTNO ORDER BY empno rows between
unbounded precedingand unbounded following) LAST,
6 LAST_VALUE(SAL) OVER(PARTITION BYDEPTNO ORDER BY empno rows between
unbounded precedingand current row) LAST2,
7 LAST_VALUE(SAL) OVER(PARTITION BYDEPTNO ORDER BY empno) last3
8 FROM EMP
9 ;
DEPTNO EMPNO SAL FIRST LAST LAST2 LAST3
---------- ---------- ---------- ---------- -------------------- ----------
10 7782 2450 2450 1300 2450 2450
10 7839 5000 2450 1300 5000 5000
10 7934 1300 2450 1300 1300 1300
20 7369 10000 10000 3000 10000 10000
20 7566 2975 10000 3000 2975 2975
20 7788 3000 10000 3000 3000 3000
20 7876 1100 10000 3000 1100 1100
20 7902 3000 10000 3000 3000 3000
30 7499 1600 1600 950 1600 1600
30 7521 1250 1600 950 1250 1250
30 7654 1250 1600 950 1250 1250
DEPTNO EMPNO SAL FIRST LAST LAST2 LAST3
---------- ---------- ---------- ---------- -------------------- ----------
30 7698 2850 1600 950 2850 2850
30 7844 1500 1600 950 1500 1500
30 7900 950 1600 950 950 950
看last3字段不是應該返回窗口的最後一個值嗎,但是結果總是讓人失望的,下面是我在pub上找到的一位大神的解釋。
--大神的解釋
對於分析函數,大家要注意:
1. 分析函數是在整個SQL查詢結束後(SQL語句中的ORDERBY的執行比較特殊)再進行的操作,也就是說
SQL語句中的ORDER BY也會影響分析函數的執行結果,請看:
SQL> select deptno,
2 empno,
3 ename,
4 sal,
5 hiredate,
6 last_value(sal) over(partition by deptno) last_value
7 from emp
8 where deptno =30;
DEPTNO EMPNO ENAME SAL HIREDATE last_value
------ ----- ---------- -------------------- -----------
30 7499ALLEN 1600.00 1981-02-20 950
30 7521WARD 1250.00 1981-02-22 950
30 7654MARTIN 1250.00 1981-09-28 950
30 7698BLAKE 2850.00 1981-05-01 950
30 7844TURNER 1500.00 1981-09-08 950
30 7900JAMES 950.00 1981-12-03 950
6 rows selected
SQL> select deptno,
2 empno,
3 ename,
4 sal,
5 hiredate,
6 last_value(sal) over(partition by deptno) last_value
7 from emp
8 where deptno =30
9 order bydeptno,mgr;
DEPTNO EMPNO ENAME SAL HIREDATE last_value
------ ----- ---------- -------------------- -----------
30 7499ALLEN 1600.00 1981-02-20 2850
30 7521WARD 1250.00 1981-02-22 2850
30 7654MARTIN 1250.00 1981-09-28 2850
30 7900JAMES 950.00 1981-12-03 2850
30 7844 TURNER 1500.00 1981-09-08 2850
30 7698BLAKE 2850.00 1981-05-01 2850
6 rows selected
SQL> select deptno,
2 empno,
3 ename,
4 sal,
5 hiredate,
6 last_value(sal) over(partition by deptno) last_value
7 from emp
8 where deptno =30
9 order bydeptno,mgr desc;
DEPTNO EMPNO ENAME SAL HIREDATE last_value
------ ----- ---------- -------------------- -----------
30 7698 BLAKE 2850.00 1981-05-01 1250
30 7499ALLEN 1600.00 1981-02-20 1250
30 7521WARD 1250.00 1981-02-22 1250
30 7900JAMES 950.00 1981-12-03 1250
30 7844TURNER 1500.00 1981-09-08 1250
30 7654MARTIN 1250.00 1981-09-28 1250
6 rows selected
從上面的結果我們分析得出:
a) 如果SQL語句中的OrderBy滿足分析函數分析時要求的排序,那麼SQL語句中的排序將先執行,分析
函數分析時就不必再排序
b) 如果SQL語句中的OrderBy不滿足分析函數分析時要求的排序,那麼SQL語句中的排序將最後在分
析函數分析結束後執行排序
2. 分析函數中包含三個分析子句:分組(Partition By), 排序(OrderBy),窗口(Window)
窗口就是分析函數分析時要處理的數據範圍,就拿SUM來說,它是SUM窗口中的記錄而不是整個分組中
的記錄,因此我們在想得到某個欄位的累計值時,我們需要把窗口指定到該分組中的第一行數據到當
前行,如果你指定該窗口從該分組中的第一行到最後一行,那麼該組中的每一個SUM值都會一樣,即整
個組的總和.
窗口子句在這裏我只說rows方式的窗口,range方式的這裏不提,此外滑動窗口也不提.窗口子句中
我們經常用到指定第一行,當前行,最後一行這樣的三個屬性.第一行是unbounded preceding,當
前行是 current row,最後一行是unbounded following.
出現窗口子句,必須指定Order By子句,如:
last_value(sal) over
(partition by deptno order by sal rowsbetween unbounded preceding and unbounded following)
以上示例指定窗口爲整個分組.
當省略窗口子句時:
a) 如果存在Order By則默認的窗口是unboundedpreceding and current row
b) 如果同時省略Order By則默認的窗口是unboundedpreceding and unbounded following
如果省略分組,則把全部記錄當成一個組:
a) 如果存在Order By則默認窗口是unboundedpreceding and current row
b) 如果這時省略Order By則窗口默認爲unboundedpreceding and unbounded following
來自 <http://www.itpub.net/thread-717608-2-1.html>
Advanced Aggregates for Analysis
LISTAGG Function
這個函數是11g新提出來的,語法如下:
LISTAGG (<expr>[, <delimiter>) WITHIN GROUP (ORDER BY <oby_expression_list>)
Expr表示你要做處理的字段。
delimiter表示分隔符。
oby_expression_list表示要按照什麼排序。
看一個例子就明白了listagg做了什麼,下面這個sql列出了一個營業部所有的人員的名稱,並使用逗號分隔。
SQL> SELECT DEPTNO,
2 LISTAGG(ename,',') WITHINGROUP(ORDER BY DEPTNO) enamelist
3 FROM EMP
4 GROUP BY DEPTNO;
DEPTNO ENAMELIST
------------------------------------------------------------
10CLARK,KING,MILLER
20ADAMS,FORD,JONES,SCOTT,SMITH
30ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
FIRST/LAST Functions
語法如下:
aggregate_functionKEEP ( DENSE_RANK LAST ORDER BY
expr [ DESC | ASC ] [NULLS { FIRST |LAST }]
[, expr [ DESC | ASC ] [NULLS { FIRST |LAST }]]...)
[OVER query_partitioning_clause]
下面來看這個例子:
找出emp表中每個部門工資的最大值和最小值
SQL> SELECT DEPTNO,
2 ENAME,
3 EMPNO,
4 SAL,
5 hiredate,
6 MAX(SAL) KEEP(DENSE_RANK FIRST ORDER BY empno) OVER(PARTITION BY DEP
TNO)"min_sal",
7 MIN(SAL) KEEP(DENSE_RANK LAST ORDER BY empno) OVER(PARTITION BY DEPT
NO)"MAX_sal"
8 FROM EMP;
DEPTNO ENAME EMPNO SAL HIREDATE min_sal MAX_sal
---------- -------------------- ---------- -------------- ---------- ----------
10 CLARK 7782 2450 09-6月 -81 2450 1300
10 KING 7839 5000 17-11月-81 2450 1300
10 MILLER 7934 1300 23-1月 -82 2450 1300
20 JONES 7566 2975 02-4月 -81 10000 3000
20 FORD 7902 3000 03-12月-81 10000 3000
20 ADAMS 7876 1100 23-5月 -87 10000 3000
20 SMITH 7369 10000 17-12月-80 10000 3000
20 SCOTT 7788 3000 19-4月 -87 10000 3000
30 WARD 7521 1250 22-2月 -81 1600 950
30 TURNER 7844 1500 08-9月 -81 1600 950
30 ALLEN 7499 1600 20-2月 -81 1600 950
DEPTNO ENAME EMPNO SAL HIREDATE min_sal MAX_sal
---------- -------------------- ---------- -------------- ---------- ----------
30 JAMES 7900 950 03-12月-81 1600 950
30 BLAKE 7698 2850 01-5月 -81 1600 950
30 MARTIN 7654 1250 28-9月 -81 1600 950
一些比較好的例子
連續數問題
要求對ID相同,num連續的,查找最小num以及val求和。
表中數據如下所示:
SQL> select * fromtest_tab;
ID NUM VAL
---------- --------------------
1 1 50
1 2 100
1 3 150
1 5 250
2 1 100
2 3 400
3 1 100
3 2 200
SQL> SELECT ID,MIN(NUM), SUM(VAL)
2 FROM (SELECT ID,
3 NUM,
4 VAL,
5 NUM - ROW_NUMBER()OVER(PARTITION BY ID ORDER BY NUM) RN --使用當前值來減去rownumber
6 FROM TEST_TAB)
7 GROUP BY ID, RN
8 ORDER BY 1, 2
9 ;
ID MIN(NUM) SUM(VAL)
---------- --------------------
1 1 300
1 5 250
2 1 100
2 3 400
3 1 300
模擬SQL*PLUS BREAK 問題
SQL*PLUS提供BREAK命令,就是當前列值與前面相同,則置NULL,這是報表常用的一種手段。
SQL> break on deptno;
SQL> select deptno,empno,ename from emp wheredeptno<30 order by deptno;
DEPTNO EMPNO ENAME
---------- ---------- ----------
10 7934 MILLER
7782 CLARK
7839 KING
20 7902 FORD
7876 ADAMS
7566 JONES
7369 SMITH
7788 SCOTT
已選擇8行。
SQL> SELECT DECODE(LAG(DEPTNO, 1) OVER(PARTITIONBY DEPTNO ORDER BY EMPNO),
2 DEPTNO,
3 NULL,
4 DEPTNO) deptno,
5 EMPNO,
6 ENAME
7 FROM EMP
8 WHERE deptno<30;
DEPTNO EMPNO ENAME
---------- ---------- ----------
10 7782 CLARK
7839 KING
7934 MILLER
20 7369 SMITH
7566 JONES
7788 SCOTT
7876 ADAMS
7902 FORD
重複行問題
SQL> select *from duprows;
ID NAME
--------------------
1 name
2 name
1 name
3 name
1 name
--通過以下方式找到重複行
SQL> SELECT *
2 FROM (SELECT ID,
3 NAME,
4 ROW_NUMBER() OVER(PARTITION BYB.ID ORDER BY B.ROWID) RN
5 FROM DUPROWS B) C
6 WHERE C.RN > 1;
ID NAME RN
-------------------- ----------
1 name 2
1 name 3
金額攤派問題
平均分派問題,如何將金額平均分攤,並且小數也分攤掉,避免誤差
SQL> select *from demo7_1;
ID AMOUNT
--------------------
1 100
2 50
SQL> select *from demo7_2;
ID PERSONS
--------------------
1 3
2 2
SELECT ID,
PERSONS,
(CASE
WHEN RN <= (AMOUNT - AMOUNT2) * 100THEN
0.01
ELSE
0
END) + JE AS JE,
AMOUNT
--然後排序,與總金額有差額的補0.01
FROM (SELECT T.*,
SUM(JE) OVER(PARTITION BY ID) ASAMOUNT2,
ROW_NUMBER() OVER(PARTITION BYID ORDER BY JE DESC) RN
FROM (
--先展開記錄數,用trunc先平均,只舍不入
SELECT TT.*
FROM (SELECT T2.ID,
T2.PERSONS,
TRUNC(T1.AMOUNT/ T2.PERSONS, 2) JE,
T1.AMOUNTAMOUNT
FROM DEMO7_1 T1,DEMO7_2 T2
WHERE T1.ID = T2.ID)TT,
--構造最大的人數序列
(SELECT LEVEL RN
FROM DUAL
CONNECT BY LEVEL <=
(SELECTMAX(PERSONS) MAX_NUM FROM DEMO7_2)) TM
WHERE TT.PERSONS >= TM.RN)T)
ID PERSONS JE AMOUNT
-------------------- ---------- ----------
1 3 33.34 100
1 3 33.33 100
1 3 33.33 100
2 2 25 50
2 2 25 50