陪君醉笑三万场,不诉离伤
两个字符串无序匹配问题
上一篇 / 下一篇 2008-08-22 10:07:26 / 个人分类:函数
查看( 33 ) /
评论( 18 )
-
junsansi
发布于2008-03-13 13:39:41
-
有点儿意思,用pl/sql实现的话很容易,如果是单条sql的话....................
先标个签,容俺随后想想~~
-
junsansi
发布于2008-03-13 14:10:16
-
[php]
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
SQL> select * from jss_tmp2;
ID ST
---------- ------------------------------
1 A1A3BCLKMBNK
2 A2A4MBKLDMSK
3 A3A6LKKLDMSK
4 DS6LKKLDMSK8
5 NKA6LKLBDSMK
SQL>
SQL> select e.*,d.value,nvl(d.ct,0) from(
2 select /*+ rule*/ c.id, c.st, max(substr(sys_connect_by_path(c.str, '-'), 2)) value, c.ct
3 from (select a.*,
4 substr(a.st, b.rn, 2) str,
5 count(id) over(partition by id) ct,
6 row_number() over(partition by id order by id) rn
7 from jss_tmp2 a,
8 (select rownum * 2 - 1 rn
9 from dual
10 connect by rownum <=
11 (select max(length(st) / 2) from jss_tmp2)) b
12 where substr(a.st, b.rn, 2) in
13 (select substr('A3MLLKNKDS', rownum * 2 - 1, 2)
14 from dual
15 connect by rownum <= length('A3MLLKNKDS') / 2)) c
16 start with rn = 1
17 connect by prior rn + 1 = rn
18 and prior id = id
19 group by c.id, c.st, c.ct)d, jss_tmp2 e
20 where d.id(+)=e.id
21 /
ID ST VALUE NVL(D.CT,0)
---------- ------------------------------ -------------------------------------------------------------------------------- -----------
1 A1A3BCLKMBNK A3-NK-LK 3
2 A2A4MBKLDMSK 0
3 A3A6LKKLDMSK LK-A3 2
4 DS6LKKLDMSK8 DS 1
5 NKA6LKLBDSMK NK-DS-LK 3
SQL>
--
[/php]
-
zhanglinjun007发布于2008-03-13 15:12:14
-

QUOTE:
原帖由 junsansi 于 2008-3-13 14:10 发表
高!!! 学习了 !!
[php]
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
SQL> select * from jss_tmp2;
ID ST
---------- ------------------------------
1 A1A3BCLKMBNK
2 A2A4MBKLDMSK
3 A3A6LKKLDMSK
4 DS6LKKLDMSK8
5 NKA6LKLBDSMK
SQL>
SQL> select e.*,d.value,nvl(d.ct,0) from(
2 select /*+ rule*/ c.id, c.st, max(substr(sys_connect_by_path(c.str, '-'), 2)) value, c.ct
3 from (select a.*,
4 substr(a.st, b.rn, 2) str,
5 count(id) over(partition by id) ct,
6 row_number() over(partition by id order by id) rn
7 from jss_tmp2 a,
8 (select rownum * 2 - 1 rn
9 from dual
10 connect by rownum
-
zhanglinjun007发布于2008-03-13 15:15:45
-
君三思的要在10G里运行,如果要在9I中运行,把其中的代码改为:
(select level * 2 - 1 rn
from (select max(length(st) / 2) len from jss_tmp2)
connect by level <=len)
-
bell6248
发布于2008-03-13 15:20:00
-
这个要求用sql语句不如用pl/sql!
SQL> select * from tmp22;
NO ST
---------- ------------------------------
1 A1A3BCLKMBNK
2 A2A4MBKLDMSK
SQL>
SQL> select no,
2 max_str st,
3 max(st) "相同值",
4 nvl(cnt, 0) "相同数量"
5 from
6 (select no,
7 replace(max_str, ',', '') max_str,
8 LTRIM(SYS_CONNECT_BY_PATH(str, ' '), ' ') st,
9 cnt
10 from
11 (select no,
12 max_str,
13 str,
14 row_number() over(partition by no order by cnt) rn,
15 cnt
16 from
17 (select tmp1.no,
18 tmp1.max_str,
19 tmp2.str,
20 decode(tmp2.str, null, null, count(tmp2.str) over(partition by no)) cnt
21 from
22 (select no,
23 st,
24 max(st) over(partition by no) max_str,
25 str,
26 cnt
27 from
28 (select no,
29 LTRIM(SYS_CONNECT_BY_PATH(str, ','), ',') st,
30 str,
31 cnt
32 from
33 (select no,
34 st,
35 str,
36 count(*) over(partition by no) cnt,
37 row_number() over(partition by no order by no) rn
38 from
39 (select a.no,
40 a.st,
41 b.rn,
42 substr(a.st, b.rn, 2) str
43 from tmp22 a,
44 (select level * 2 - 1 rn
45 from (select max(length(st)) len from tmp22)
46 connect by level <= len) b
47 order by a.no, b.rn)
48 where str is not null)
49 start with rn = 1
50 connect by prior rn + 1 = rn and prior no = no)) tmp1,
51 (select substr('A3MLLKNKDS', rownum * 2 - 1, 2) str
52 from dual
53 connect by rownum <= length('A3MLLKNKDS') / 2) tmp2
54 where tmp1.str = tmp2.str(+)))
55 start with rn = 1
56 connect by prior rn + 1 = rn and prior cnt = cnt and prior no = no)
57 group by no, max_str, cnt;
NO ST 相同值 相同数量
---------- -------------------- ------------------------ ----------------------------------------
1 A1A3BCLKMBNK A3 LK NK 3
2 A2A4MBKLDMSK 0
SQL>
[ 本帖最后由 bell6248 于 2008-3-13 15:21 编辑 ]
-
junsansi
发布于2008-03-13 15:32:09
-
QUOTE:
原帖由 bell6248 于 2008-3-13 15:20 发表

这个要求用sql语句不如用pl/sql!
SQL> select * from tmp22;
NO ST
---------- ------------------------------
1 A1A3BCLKMBNK
2 A2A4MBKLDMSK
SQL>
SQL> select no,
2 max_str st,
3 max(st) "相同值",
4 nvl(cnt, 0) "相同数量"
5 from
6 (select no,
7 replace(max_str, ',', '') max_str,
8 LTRIM(SYS_CONNECT_BY_PATH(str, ' '), ' ') st,
9 cnt
10 from
11 (select no,
12 max_str,
13 str,
14 row_number() over(partition by no order by cnt) rn,
15 cnt
16 from
17 (select tmp1.no,
18 tmp1.max_str,
19 tmp2.str,
20 decode(tmp2.str, null, null, count(tmp2.str) over(partition by no)) cnt
21 from
22 (select no,
23 st,
24 max(st) over(partition by no) max_str,
25 str,
26 cnt
27 from
28 (select no,
29 LTRIM(SYS_CONNECT_BY_PATH(str, ','), ',') st,
30 str,
31 cnt
32 from
33 (select no,
34 st,
35 str,
36 count(*) over(partition by no) cnt,
37 row_number() over(partition by no order by no) rn
38 from
39 (select a.no,
40 a.st,
41 b.rn,
42 substr(a.st, b.rn, 2) str
43 from tmp22 a,
44 (select level * 2 - 1 rn
45 from (select max(length(st)) len from tmp22)
46 connect by level
-
adaiagua发布于2008-03-13 15:34:00
-
主要是合并匹配字符串那部分费事,用SYS_CONNECT_BY_PATH的话,SQL必然冗长。。。
如果能用自定义聚合函数实现的话,sql就简单了很多
select A.NO, MIN(A.ST), strcat(C.SUBST2), COUNT(*)
from A
,(
select substr('A3MLLKNKDS', level * 2 - 1, 2) as subST2
from dual
connect by level <= length('A3MLLKNKDS') / 2
) C
where mod(instr(A.ST, C.SUBST2(+)), 2) = 1
group by A.NO
strcat的定义参考
http://www.cnblogs.com/sunsonbaby/archive/2005/01/21/95435.html
[ 本帖最后由 adaiagua 于 2008-3-13 15:38 编辑 ]
-
bell6248
发布于2008-03-13 15:43:08
-
QUOTE:
原帖由 adaiagua 于 2008-3-13 15:34 发表
好啊, 又有人提供的一种方法!
主要是合并匹配字符串那部分费事,用SYS_CONNECT_BY_PATH的话,SQL必然冗长。。。
如果能用自定义聚合函数实现的话,sql就简单了很多
select A.NO, MIN(A.ST), strcat(C.SUBST2), COUNT(*)
from A
,(
select substr('A3MLLKNKDS', level * 2 - 1, 2) as subST2
from dual
connect by level
-
junsansi
发布于2008-03-13 15:48:25
-
如果用函数实现行列转换,操作方式就更灵活的,野花的blog里我记的专门有篇文章总结这个~~
不过我觉着事有两面性,毕竟对于行列转换并非常见应用,多数情况下都是特殊需求,单纯为某个特殊需求弄个函数呵呵,我觉着dba也不一定乐意操作啊~~~
而且像论坛这种回答问题的形式,人家问行列转换你贴个函数上去,人家也未必会采用,所以一条sql实现吧,只当熟练语法了
-
adaiagua发布于2008-03-13 16:03:46
-
仁者见仁,智者见智,
权当凑个热闹吧。。。
-
louis_xu
发布于2008-03-13 16:07:25
-
三思哥哥就是牛啊
-
louis_xu
发布于2008-03-13 17:19:43
-
select rownum * 2 - 1 rn
from dual
connect by rownum <= (select max(length(st) / 2)
from jss_tmp2)
我执行这段报错:ORA-01473: cannot have subqueries in CONNECT BY clause
WHY?
-
louis5421发布于2008-03-13 18:33:14
-
不能嵌套查询 connect by
-
louis5421发布于2008-03-13 18:35:57
-

QUOTE:
原帖由 adaiagua 于 2008-3-13 15:34 发表
支持兄弟,这样多清楚啊,一个简单的功能非得用sql来实现,看着复杂而且不利于维护!
主要是合并匹配字符串那部分费事,用SYS_CONNECT_BY_PATH的话,SQL必然冗长。。。
如果能用自定义聚合函数实现的话,sql就简单了很多
select A.NO, MIN(A.ST), strcat(C.SUBST2), COUNT(*)
from A
,(
select substr('A3MLLKNKDS', level * 2 - 1, 2) as subST2
from dual
connect by level
-
DragonBill
发布于2008-03-14 09:52:22
-
mark
-
DragonBill
发布于2008-03-14 12:35:45
-
QUOTE:
原帖由 junsansi 于 2008-3-13 15:48 发表

如果用函数实现行列转换,操作方式就更灵活的,野花的blog里我记的专门有篇文章总结这个~~
不过我觉着事有两面性,毕竟对于行列转换并非常见应用,多数情况下都是特殊需求,单纯为某个特殊需求弄个函数呵呵,我觉着dba也不一定乐意操作啊~~~
而且像论坛这种回答问题的形式,人家问行列转换你贴个函数上去,人家也未必会采用,所以一条sql实现吧,只当熟练语法了
对, 我觉得像这种问题: 能用一条SQL完成的, 就用一条SQL,
权当练习对SQL的熟练程度
-
DragonBill
发布于2008-03-14 12:36:10
-
WITH A AS
(
SELECT 'A1A3BCLKMBNK' AS STR FROM DUAL
UNION
SELECT 'A2A4A3KLDMNK' AS STR FROM DUAL
)
SELECT STR, SUB_STR_LEN / 2 AS "Frequence", SUB_STR
FROM
(
SELECT STR, LTRIM(SYS_CONNECT_BY_PATH(SUB_STR, ' '), ' ') AS SUB_STR,
FLAG, SUB_STR_LEN
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY STR ORDER BY STR) AS SEQ, STR,
(LENGTHB(STR) - LENGTHB(REPLACE(STR,SUB_STR, '')))/2 AS FLAG,
SUB_STR,
COUNT(STR) OVER (PARTITION BY STR) * 2 AS SUB_STR_LEN
FROM A,
(SELECT SUBSTR('A3MLLKNKDS', (LEVEL-1)*2+1, 2) SUB_STR
FROM DUAL
CONNECT BY LEVEL <= LENGTHB('A3MLLKNKDS')/2
) B
WHERE (LENGTHB(STR) - LENGTHB(REPLACE(STR,SUB_STR, '')))/2 > 0
)
CONNECT BY PRIOR SEQ + 1 = SEQ AND PRIOR STR = STR
)
WHERE LENGTH(REPLACE(SUB_STR, ' ', '')) = SUB_STR_LEN;
-
wghxwl12
发布于2008-03-18 14:51:31
-
感谢大家踊跃回帖
标题搜索
日历
|
|||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
| 1 | 2 | 3 | 4 | 5 | 6 | ||||
| 7 | 8 | 9 | 10 | 11 | 12 | 13 | |||
| 14 | 15 | 16 | 17 | 18 | 19 | 20 | |||
| 21 | 22 | 23 | 24 | 25 | 26 | 27 | |||
| 28 | 29 | 30 | 31 | ||||||
我的存档
数据统计
- 访问量: 1500
- 日志数: 1399
- 建立时间: 2007-12-14
- 更新时间: 2008-11-20
