今天写了下面这一段SQL语句, 在写之前总觉得有更简便的方法, 可就是没有想出来:
SELECT
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(TABLE_NAME,'0','#'),
'1','#') ,'2','#') ,'3','#') ,'4','#')
,'5','#') ,'6','#') ,'7','#') ,'8','#') ,'9','#') PATTERN_NAME
FROM USER_TABLES
下班时坐地铁, 突然想到了Translate函数, 原来可以这么简单:
SELECT
TRANSLATE(TABLE_NAME,'0123456789','##########') PATTERN_NAME
FROM USER_TABLES
我写这个SQL是用来找出一些表结构应当相同的表, 最终的SQL应当如下:
SELECT TABLE_NAME FROM USER_TABLES
WHERE TRANSLATE(TABLE_NAME,'0123456789','##########') IN
(SELECT
TRANSLATE(TABLE_NAME,'0123456789','##########') PATTERN_NAME
FROM USER_TABLES
GROUP BY TRANSLATE(TABLE_NAME,'0123456789','##########')
HAVING COUNT(*) > 1)
看来选择最佳的方法是很必要的.
留言 (6)
还有更简洁的, 运用正则表达式 替换 或者 查找:
select REGEXP_REPLACE(TABLE_NAME, '[1-9]', '#' )
from cat;
Posted by 木匠 | Apr 25, 2007 6:24 AM
还没有全部到10g啊, 学了Perl后, 正则表达式是第一个想到的.
Posted by anysql | Apr 25, 2007 8:42 AM
提供一个只需要访问一次use_tables的方法
SELECT table_name FROM(
SELECT TABLE_NAME,RATIO_TO_REPORT (1) over(PARTITION BY TRANSLATE(TABLE_NAME,'0123456789','##########') ) AS r
FROM USER_TABLES
) WHERE r < 1
Posted by rollingpig | May 9, 2007 12:16 PM
改进型:
SELECT * FROM(
SELECT TABLE_NAME, count(*) over (PARTITION BY REGEXP_REPLACE(TABLE_NAME, '[0-9]+', '#' ) ) AS tab_cnt
, REGEXP_REPLACE(TABLE_NAME, '[0-9]+', '#' ) tran_tab
FROM USER_TABLES
) WHERE tab_cnt > 1
优点:
1) 两位数,3位数,n位数 都可以.
2) Count(*) over (PARTITION BY)
更容易理解, RATIO_TO_REPORT 分析函数有的用过了.
我最近正在学习 SQL Analytic Functions, 感谢 rollingpig 给出RATIO_TO_REPORT的这个用法.
Posted by 木匠 | May 11, 2007 3:15 AM
REGEXP_REPLACE(TABLE_NAME, '[1-9]', '#' )
更改成,
REGEXP_REPLACE(TABLE_NAME, '[1-9]+', '#' )
替换1到任意多个数字.
Posted by 木匠 | May 11, 2007 3:17 AM
运行结果:
TABLE_NAME TAB_CNT TRAN_TAB
-- -- ---
LOGMNR_HEADER2$ 2 LOGMNR_HEADER#$
LOGMNR_HEADER1$ 2 LOGMNR_HEADER#$
PARTS2 2 PARTS#
PARTS1 2 PARTS#
T101 4 T#
T2 4 T#
T1 4 T#
T3 4 T#
Posted by 木匠 | May 11, 2007 3:24 AM