如何为表中多条记录分别实现构造结果集(三)
上一篇 / 下一篇 2008-04-16 23:53:36 / 个人分类:ORACLE
前一段用SQL实现了一个复杂的功能,但是留下了一个问题一直没有真正的解决,那就是如何同时为表中的多条记录分别实现构造结果集。
利用MODEL语句来实现结果集构造。
问题源自:一个复杂问题的求解过程(一):http://yangtingkun.itpub.net/post/468/456641
如何为表中多条记录分别实现构造结果集(一):http://yangtingkun.itpub.net/post/468/459848
如何为表中多条记录分别实现构造结果集(二):http://yangtingkun.itpub.net/post/468/459938
上面一篇文章给出了利用自定义类型的SQL写法,那么完全使用SQL功能真的不能实现吗,这篇文章给出一个完全使用SQL实现的方法。
由于MODEL语句是
SQL> SELECT ID, VALUE, POWER, RESULT
"[)fW(AX iX0 2 FROM TITPUB个人空间%i] ^I1zGE
3 MODEL
/oi-vKI.FC0 4 PARTITION BY (ID, VALUE, POWER)ITPUB个人空间6[3Ex
R1Xl AB:E
5 DIMENSION BY (0 RESULT)
3oL?lM+@0 6 MEASURES (0 V)
h6sL$p/Xim'n0 7 RULESITPUB个人空间yI3n6m,d8HK#j g
8 (
)mOc,X/H?${0 9 V[
xI}-sv~0 10 FOR RESULT INITPUB个人空间RJyQNt*{L?Y
11 (
CX'c-x!ol0 12 SELECT ROWNUM FROM DUALITPUB个人空间n(V4D!\~W$c8e
13 CONNECT BY LEVEL <= (SELECT MAX(POWER) FROM T)ITPUB个人空间Ne X*HCM7p$A HG
14 )
pg {#aD)_0 15 ] = 1ITPUB个人空间Z1Sq#NE4N*wt0DI(T
16 )ITPUB个人空间8a9}K#H
wa^3V
17 ORDER BY 1, 4;
ID VALUE POWER RESULTITPUB个人空间q7g'G;?6XhZ@3ps
---------- ---------- ---------- ----------
@$PQ1n?d
Y0 1 2 3 0ITPUB个人空间
tA"VLCGa;e/W/J
1 2 3 1
)tf;L\ T|:]G$u-B0 1 2 3 2
${l'\NE*l!qK0 1 2 3 3
j
\.vA/b$UlW4y0 1 2 3 4ITPUB个人空间Y#Q)G8p)rapt
2 1 2 0
d1BD4{l0 2 1 2 1
4p[!n(R/m;w'z?!Ea0 2 1 2 2ITPUB个人空间jZ6eiD:p$PZO+_
2 1 2 3
/t4kOEdM;O0 2 1 2 4
C:m:m s \F5gq(il0 3 4 4 0
OH$U|A0 3 4 4 1ITPUB个人空间(X7Uo Ap#`{
3 4 4 2ITPUB个人空间qqDb$k:\5jhj(UD
3 4 4 3
9`s8~#`"{0 3 4 4 4ITPUB个人空间hdu_*Cn2Z5C0W~9J
4 5 2 0
%X?Z
yFh.eFQ0 4 5 2 1ITPUB个人空间s$e XX*w)Z
4 5 2 2
3W)EV4?zW0 4 5 2 3
9Dw3U
W W
c0 4 5 2 4ITPUB个人空间A~|W6d3U
5 4 3 0
D!P,Wk\.K5mx5|r0 5 4 3 1ITPUB个人空间9e+~w3xn1t
5 4 3 2ITPUB个人空间;B;t-mr&k1S8S
5 4 3 3ITPUB个人空间B"|YF!DkI
5 4 3 4
已选择25行。
说是分步介绍,其实也只分了两步,上面这个SQL基本上实现了整个SQL的核心部分。
首先介绍一下语法,PARTITION BY语句列出数据的分区列,这个分区的概念和分析函数中的PARTITION BY语句类似。
DIMENSION BY语句指定维度列,通过这个列来控制和设置需要修改的列。
MEASURES BY语句指定定制新增的列。
这个例子中主要是利用DIMENSION BY语句的构造记录功能,对ID, VALUE和POWER都不需要进行任何的处理,因此将这3列放到PARTITION BY语句中。
由于需要DIMENSION BY来构造结果集,因此构造一个RESULT列。
MEASURES BY语句指定的列在本例子中没有用处,只是为了实现的语法需要,因此随意构造一个V列。
这里用到了FOR LOOP IN SUBQUERY的方式构造维度列的值,由于没有办法为每个ID分别生成构造结果集,因此这里只能表中最大的POWER来构造结果集,这对于大部分记录都会存在重复数据的问题,不过好在这里的重复记录和第一篇文章中的不同,这里重复记录是成线形增长的,因此不会对性能带来太大的负担。
有了上面这个结果集,要得到期望的最终结果就很容易了,只需要在这个的基础上过滤掉重复记录就可以了:
SQL> WITH T1ITPUB个人空间6n]3e
NU[d'y
Swo
2 ASITPUB个人空间^?Ri2j
3 (
Amd.K"]tW0 4 SELECT ID, VALUE, POWER, RESULT
3MAv1Mn1DTFS8OH0 5 FROM TITPUB个人空间#SZD8KQ
6 MODELITPUB个人空间h
ro)u(u
7 PARTITION BY (ID, VALUE, POWER)
Qoc1p.iH8wp0 8 DIMENSION BY (0 RESULT)
2~hJ_{0 9 MEASURES (0 V)
XC JV:K c/QV,s"J0 10 RULES
:FDwa)Q
k)`1m6F$x0 11 (
sN"@j@[[HSM0 12 V[ITPUB个人空间I-ae1u/X:{%_G-O%J
13 FOR RESULT INITPUB个人空间3k%HfG5tY2^7F8g
14 (ITPUB个人空间
c C3@-Ayr/S
15 SELECT ROWNUM FROM DUALITPUB个人空间NdW@G/uXd
16 CONNECT BY LEVEL <= (SELECT MAX(POWER) FROM T)ITPUB个人空间y-U.}OYuEA{
17 )
m;C$`_4XD0 18 ] = 1ITPUB个人空间-iX*V+`2|\5Y0Q
19 )
H5{MiU*C/u0 20 )ITPUB个人空间 oJt:_^!Mn
21 SELECT ID, VALUE, POWER, RESULT * VALUE RESULTITPUB个人空间9q_w(m
m+~u
22 FROM T1
2~ E0Va6tn4l0 23 WHERE RESULT < POWER
/Z&m/q8f,c0 24 ORDER BY 1, 4;
ID VALUE POWER RESULT
(OAv)G`4e0---------- ---------- ---------- ----------ITPUB个人空间t
o)^)I9GFA
1 2 3 0ITPUB个人空间?e.HWnb;J\/H'S
1 2 3 2
1Y0Rc7Og$c o0 1 2 3 4
SA0a
W1O+A0 2 1 2 0
4W df%LJ0 2 1 2 1ITPUB个人空间S0z#l$pP(W
3 4 4 0
6jvP:\CaT
Q5{$~0 3 4 4 4
rW(Ov8dZOi;Y0 3 4 4 8ITPUB个人空间.t,k4wJ?.S C
3 4 4 12ITPUB个人空间_4@6F$kP[(QMAp
4 5 2 0
,XSQ{B3|k0 4 5 2 5
%~-`*c/hvlC0 5 4 3 0
id`9p'zk.gC*K0 5 4 3 4ITPUB个人空间,](fv Xl9I X$W
5 4 3 8
已选择14行。
下面看看这条语句的性能能否满足要求:
SQL> INSERT INTO T SELECT 5 + ID, VALUE, POWER FROM T;
已创建5行。
SQL> INSERT INTO T SELECT 10 + ID, VALUE, POWER FROM T;
已创建10行。
SQL> INSERT INTO T SELECT 20 + ID, VALUE, POWER FROM T;
已创建20行。
SQL> SET TIMING ONITPUB个人空间n#hrdn
SQL> SET AUTOT TRACE
F_qw2l!xo+S0SQL> WITH T1ITPUB个人空间2O!o:\*B6y`@4iD2]
2 ASITPUB个人空间-K!t$n'nyvN
3 (
v1j'Z\k5`0 4 SELECT ID, VALUE, POWER, RESULTITPUB个人空间|b([0I*jq'j
5 FROM T
8mNL Wg"z1{`a0 6 MODELITPUB个人空间bsU+\7VR
7 PARTITION BY (ID, VALUE, POWER)ITPUB个人空间4ti$T |!w~2Mm8b9x8I:c
8 DIMENSION BY (0 RESULT)ITPUB个人空间 sb6fiNJx
9 MEASURES (0 V)ITPUB个人空间{+v/u
VU+y![Ri(d
10 RULESITPUB个人空间2DQ"i3GV,^
11 (ITPUB个人空间}8^.Cw0~~@
12 V[
;T p:y-\7UaV(VOT3g0 13 FOR RESULT INITPUB个人空间&YXx Ph
14 (
Lg'z6}6}t0 15 SELECT ROWNUM FROM DUALITPUB个人空间%rWCM,M%Qx
16 CONNECT BY LEVEL <= (SELECT MAX(POWER) FROM T)
?*Lh-I;a0T0E0 17 )ITPUB个人空间d0r(G2} UM0c+g}6O
18 ] = 1
D])VWu|2T N2g0k0 19 )
"HX;f9C1ot$rK0 20 )ITPUB个人空间-q-T)w|a
21 SELECT ID, VALUE, POWER, RESULT * VALUE RESULT