|
改成下面这样,重复啰嗦地效的SQL:
SQL> with function fn_val (p_nlist in varchar2)
2 return int
3 is
4 l_res int := 0;
5 begin
6 with t as (
7 select a.nlist,a.n,p1,p2
8 from (
9 select nlist, regexp_substr(nlist, '[^,]+', 1, level) n
10 from (select p_nlist nlist from dual)
11 connect by level <= regexp_count(nlist, ',') + 1
12 ) a,
13 (
14 select row_number() over(order by p1.n,p2.n) as n, p1.n p1, p2.n p2
15 from (
16 select level n,
17 ceil(level / 3) x,
18 decode(mod(level, 3), 0, 3, mod(level, 3)) y
19 from dual
20 connect by level <= 9
21 ) p1,
22 (
23 select level n,
24 ceil(level / 3) x,
25 decode(mod(level, 3), 0, 3, mod(level, 3)) y
26 from dual
27 connect by level <= 9
28 ) p2
29 where abs(p1.x - p2.x) + abs(p1.y - p2.y) = 1
30 and p1.n < p2.n
31 ) b
32 where a.n = b.n),
33 s (lvl,nlist,val,sp,ep) as (select 1,n,power(2,n),p1,p2 from t
34 union all
35 select s.lvl + 1,
36 s.nlist||','||t.n,
37 s.val + power(2,t.n),
38 s.sp,
39 case when s.ep = t.p1 then t.p2
40 when s.ep = t.p2 then t.p1
41 end
42 from s,t
43 where bitand(s.val,power(2,t.n))=0
44 and (s.ep = t.p1 or s.ep = t.p2)
45 )
46 select sum(power(2,first_node))
47 into l_res
48 from (
49 select distinct substr(nlist,1,instr(nlist,',',1,1)-1) first_node
50 from s
51 where sp = ep
52 );
53 return l_res;
54 end;
55 t_point (n, x, y) as (
56 select level n,
57 ceil(level / 3),
58 decode(mod(level, 3), 0, 3, mod(level, 3))
59 from dual
60 connect by level <= 9),
61 t_line (n,p1,p2) as (
62 select row_number() over(order by p1.n,p2.n), p1.n, p2.n
63 from t_point p1, t_point p2
64 where abs(p1.x - p2.x) + abs(p1.y - p2.y) = 1
65 and p1.n < p2.n ),
66 shape (lvl,nlist,val,plist,rn) as (select 1,
67 cast(n as varchar2(100)),
68 power(2,n),
69 p1||','||p2,
70 1
71 from t_line
72 union all
73 select s.lvl + 1,
74 s.nlist||','||a.n,
75 s.val + power(2,a.n),
76 s.plist||','||a.p1||','||a.p2,
77 row_number() over(partition by s.lvl+1,s.val + power(2,a.n)
78 order by s.val + power(2,a.n)
79 ) rn
80 from shape s,t_line a
81 where bitand(s.val,power(2,a.n))=0
82 and (instr(s.plist,a.p1) > 0
83 or instr(s.plist,a.p2) > 0)
84 and lvl < 12
85 and rn = 1),
86 t_shape (lvl,val,nlist) as (
87 select lvl,val,min(nlist) nlist
88 from shape
89 group by lvl,val
90 order by lvl,val )
91 select count(t.nlist)
92 from T_SHAPE t
93 where fn_val(t.nlist) = val
94 /
COUNT(T.NLIST)
--------------
42 |
|