楼主: newkid

连TOM也答不上来的SQL问题,你来试试看!

[复制链接]
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
21#
发表于 2010-4-9 14:15 | 只看该作者

回复 #19 jiqing1004 的帖子

有的最后多1个,

COL1       COL2
---------- ---------
a          b,c,d,e
a,b        c,d,e
a,b,c      d,e
a,b,c,d    e
a,b,c,e    d,
a,b,d      c,e
a,b,d,e    c,
a,b,e      c,d,
a,c        b,d,e
a,c,d      b,e
a,c,d,e    b,

再套一个RTRIM

with tmp as
    (select  TRIM(REGEXP_SUBSTR(:x, '[^,]+', 1, level)) val from dual
       connect by level <= length(regexp_replace(:x,'[^,]*'))+1)
select LTRIM(col1,',') col1,
       RTRIM(LTRIM(REGEXP_REPLACE(translate(:x,col1,','),'(,){2,}', ','),','),',') col2
  from (select sys_connect_by_path (val, ',') col1
          from tmp
        connect by val > prior val )
where LTRIM(translate(:x,col1,','),',') is not null
order by col1;

[ 本帖最后由 〇〇 于 2010-4-9 14:24 编辑 ]

使用道具 举报

回复
论坛徽章:
25
奥运会纪念徽章:射击
日期:2013-01-28 09:12:182014年新春福章
日期:2014-02-18 16:41:11马上有车
日期:2014-02-18 16:41:11马上有车
日期:2014-03-20 16:13:24马上有房
日期:2014-03-20 16:14:11马上有钱
日期:2014-03-20 16:14:11马上有对象
日期:2014-03-20 16:14:11马上加薪
日期:2014-03-20 16:14:11喜羊羊
日期:2015-04-09 18:46:34秀才
日期:2016-03-24 09:20:52
22#
发表于 2010-4-9 14:16 | 只看该作者
tom看了都会傻了
各位很牛

使用道具 举报

回复
论坛徽章:
26
2010年世界杯参赛球队:智利
日期:2010-07-03 17:16:26比亚迪
日期:2014-01-16 17:12:41宝马
日期:2014-01-24 10:32:252014年新春福章
日期:2014-02-18 16:44:08马上有对象
日期:2014-02-18 16:44:08马上有对象
日期:2014-03-05 21:30:32马上有车
日期:2014-03-11 16:46:45优秀写手
日期:2014-03-25 05:59:50马上加薪
日期:2014-03-26 16:46:30问答徽章
日期:2014-05-09 16:40:36
23#
发表于 2010-4-9 15:28 | 只看该作者

用的鸟枪法,打到的不多,而且最大支持不了多少字符,呵呵:

scott@ORCL>select * from v$version where rownum<=2;

BANNER
----------------------------------------------------------------
Personal Oracle Database 10g Release 10.2.0.1.0 - Production
PL/SQL Release 10.2.0.1.0 - Production



create table t(x varchar2(10));

create or replace procedure test(x in varchar2)
     as
    type test_table is table of varchar2(4000) index by binary_integer;
    l_test_table test_table;
    l_test_table1 test_table;
    cursor c_test is select * from t;
  begin
    for i in 1..10000 loop
      select  substr(x,round(dbms_random.value(1,length(x))),round(dbms_random.value(1,length(x)))) into l_test_table(i) from dual;
      insert into  t values(l_test_table(i));
    end loop;
delete from t where rowid not in (select min(rowid) from t group by x);
  open c_test;
  fetch c_test bulk collect into l_test_table1;
    for i in 1..l_test_table1.count loop
     dbms_output.put_line(l_test_table1(i)||'     '||replace(translate(x,l_test_table1(i),'##########'),'#',''));
   end loop;
delete from t;
  close c_test;
  end;

scott@ORCL>exec test('abcde');
d     abce
bcde     a
e     abcd
cde     ab
de     abc
cd     abe
bcd     ae
b     acde
c     abde
abc     de
bc     ade
a     bcde
abcd     e
abcde
ab     cde

PL/SQL 过程已成功完成。

呵呵,见笑了。

[ 本帖最后由 ocpdba591 于 2010-4-9 15:39 编辑 ]

使用道具 举报

回复
论坛徽章:
24
CTO参与奖
日期:2009-01-15 11:42:46慢羊羊
日期:2015-03-04 14:19:44世界杯纪念徽章
日期:2014-07-14 11:31:462014年世界杯参赛球队: 伊朗
日期:2014-06-17 16:03:05ITPUB元老
日期:2010-08-06 21:59:43开发板块每日发贴之星
日期:2010-07-28 01:01:01博彩之星
日期:2010-07-12 13:14:39世界杯纪念徽章
日期:2010-07-12 13:08:00授权会员
日期:2010-06-21 15:37:282015年新春福章
日期:2015-03-06 11:57:31
24#
发表于 2010-4-9 15:36 | 只看该作者
oh

使用道具 举报

回复
论坛徽章:
211
国际米兰
日期:2010-01-11 10:26:28ITPUB评论家
日期:2007-11-04 01:35:51季节之章:春
日期:2011-04-03 16:30:30热刺
日期:2009-09-21 10:54:48天枰座
日期:2015-11-05 16:32:03月度论坛发贴之星
日期:2010-05-01 02:15:42生肖徽章:狗
日期:2006-10-01 00:29:23BLOG每周发帖之星
日期:2009-08-30 01:35:31BLOG每日发帖之星
日期:2009-08-28 01:01:02妮可·罗宾
日期:2016-10-19 10:45:04
25#
发表于 2010-4-9 16:55 | 只看该作者
amazing

使用道具 举报

回复
论坛徽章:
407
紫蛋头
日期:2012-05-21 10:19:41迷宫蛋
日期:2012-06-06 16:02:49奥运会纪念徽章:足球
日期:2012-06-29 15:30:06奥运会纪念徽章:排球
日期:2012-07-10 21:24:24鲜花蛋
日期:2012-07-16 15:24:59奥运会纪念徽章:拳击
日期:2012-08-07 10:54:50奥运会纪念徽章:羽毛球
日期:2012-08-21 15:55:33奥运会纪念徽章:蹦床
日期:2012-08-21 21:09:51奥运会纪念徽章:篮球
日期:2012-08-24 10:29:11奥运会纪念徽章:体操
日期:2012-09-07 16:40:00
26#
发表于 2010-4-9 17:01 | 只看该作者

回复 #23 ocpdba591 的帖子

bd ace没有算出来

使用道具 举报

回复
论坛徽章:
26
2010年世界杯参赛球队:智利
日期:2010-07-03 17:16:26比亚迪
日期:2014-01-16 17:12:41宝马
日期:2014-01-24 10:32:252014年新春福章
日期:2014-02-18 16:44:08马上有对象
日期:2014-02-18 16:44:08马上有对象
日期:2014-03-05 21:30:32马上有车
日期:2014-03-11 16:46:45优秀写手
日期:2014-03-25 05:59:50马上加薪
日期:2014-03-26 16:46:30问答徽章
日期:2014-05-09 16:40:36
27#
发表于 2010-4-9 17:48 | 只看该作者
呵呵,是的;除非打很多枪,否则打不中的

[ 本帖最后由 ocpdba591 于 2010-4-9 17:49 编辑 ]

使用道具 举报

回复
论坛徽章:
69
生肖徽章2007版:羊
日期:2008-11-14 14:42:19复活蛋
日期:2011-08-06 08:59:05ITPUB十周年纪念徽章
日期:2011-11-01 16:19:412012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20版主4段
日期:2012-05-15 15:24:11
28#
发表于 2010-4-9 22:06 | 只看该作者
原帖由 ocpdba591 于 2010-4-9 17:48 发表
呵呵,是的;除非打很多枪,否则打不中的

使用道具 举报

回复
论坛徽章:
520
奥运会纪念徽章:垒球
日期:2008-09-15 01:28:12生肖徽章2007版:鸡
日期:2008-11-17 23:40:58生肖徽章2007版:马
日期:2008-11-18 05:09:48数据库板块每日发贴之星
日期:2008-11-29 01:01:02数据库板块每日发贴之星
日期:2008-12-05 01:01:03生肖徽章2007版:虎
日期:2008-12-10 07:47:462009新春纪念徽章
日期:2009-01-04 14:52:28数据库板块每日发贴之星
日期:2009-02-08 01:01:03生肖徽章2007版:蛇
日期:2009-03-09 22:18:532009日食纪念
日期:2009-07-22 09:30:00
29#
 楼主| 发表于 2010-4-9 22:55 | 只看该作者
哇!真是八仙过海各显神通,我隆重宣布开发版进入鼎盛时期!

以下是我的几种方法,等会再和各位的对照一下:

VAR s VARCHAR2(200);
EXEC :s := 'A,B,C,D,E,F';

用BITAND的思路:
WITH t AS (
SELECT REGEXP_SUBSTR(:s,'[^,]+',1,ROWNUM) s,COUNT(*) OVER() cnt, ROWNUM rn
  FROM DUAL
CONNECT BY ROWNUM<=LENGTH(:s)-LENGTH(REPLACE(:s,','))+1
)
, t2 AS (
SELECT ROWNUM id
  FROM DUAL
CONNECT BY ROWNUM < POWER(2, (SELECT count(*) FROM t)) - 1
)
, bits AS (
SELECT id, BITAND(id, POWER(2, rn)) bit,s
FROM t, t2
)
SELECT id,WMSYS.WM_CONCAT(CASE WHEN bit=0 THEN s END),WMSYS.WM_CONCAT(CASE WHEN bit<>0 THEN s END)
  FROM bits
GROUP BY id;

-----------------------------------------

假设全部元素都为单字符,用TRANSLATE求补集:
WITH t AS (
SELECT REGEXP_SUBSTR(:s,'[^,]+',1,ROWNUM) s,COUNT(*) OVER() cnt
  FROM DUAL
CONNECT BY ROWNUM<=LENGTH(:s)-LENGTH(REPLACE(:s,','))+1
)
,t2 AS (
SELECT SYS_CONNECT_BY_PATH(s,',') s2
  FROM t
CONNECT BY s>PRIOR s AND LEVEL<cnt
)
SELECT LTRIM(s2,',') AS COL1
      ,RTRIM(LTRIM(REGEXP_REPLACE(TRANSLATE(:s,s2,LPAD(',',LENGTH(s2),',')),'(,){2,}','\1'),','),',') AS COL2
  FROM t2;

-----------------------
列转行,用分区外连接求补集,再用WM_CONCAT拼接:
WITH t AS (
SELECT REGEXP_SUBSTR(:s,'[^,]+',1,ROWNUM) s,COUNT(*) OVER() cnt
  FROM DUAL
CONNECT BY ROWNUM<=LENGTH(:s)-LENGTH(REPLACE(:s,','))+1
)
,t2 AS (
SELECT ROWNUM AS id, SYS_CONNECT_BY_PATH(s,',') AS s2, LEVEL AS lvl
  FROM t
CONNECT BY s>PRIOR s AND LEVEL<cnt
)
,t3 AS (
SELECT id
      ,REGEXP_SUBSTR(s2,'[^,]+',1,rn) S3
  FROM t2
      ,(SELECT ROWNUM rn FROM DUAL CONNECT BY ROWNUM <=(SELECT MAX(cnt) FROM t))
WHERE t2.lvl>=rn     
)
SELECT t3.id
      ,RTRIM(REGEXP_REPLACE(WMSYS.WM_CONCAT(s3),'(,){2,}','\1'),',')
      ,RTRIM(REGEXP_REPLACE(WMSYS.WM_CONCAT(CASE WHEN s3 IS NULL THEN s END),'(,){2,}','\1'),',')
  FROM t3 PARTITION BY (id)
       RIGHT JOIN t
       ON t3.s3 = t.s
GROUP BY id;


-----------------------
同上,用xmlagg拼接:

WITH t AS (
SELECT REGEXP_SUBSTR(:s,'[^,]+',1,ROWNUM) s,COUNT(*) OVER() cnt
  FROM DUAL
CONNECT BY ROWNUM<=LENGTH(:s)-LENGTH(REPLACE(:s,','))+1
)
,t2 AS (
SELECT ROWNUM AS id, SYS_CONNECT_BY_PATH(s,',') AS s2, LEVEL AS lvl
  FROM t
CONNECT BY s>PRIOR s AND LEVEL<cnt
)
,t3 AS (
SELECT id
      ,REGEXP_SUBSTR(s2,'[^,]+',1,rn) S3
  FROM t2
      ,(SELECT ROWNUM rn FROM DUAL CONNECT BY ROWNUM <=(SELECT MAX(cnt) FROM t))
WHERE t2.lvl>=rn     
)
SELECT t3.id
      ,RTRIM(REGEXP_REPLACE(xmlagg(xmlelement (elmt,s3||',') order by s3).extract ('//text()'),'(,){2,}','\1'),',')
      ,RTRIM(REGEXP_REPLACE(xmlagg(xmlelement (elmt,(CASE WHEN s3 IS NULL THEN s END)||',') order by s).extract ('//text()'),'(,){2,}','\1'),',')
  FROM t3 PARTITION BY (id)
       RIGHT JOIN t
       ON t3.s3 = t.s
GROUP BY id;
-----------------------
列转行,用MINUS求补集,用CONNECT BY拼接:

WITH t AS (
SELECT REGEXP_SUBSTR(:s,'[^,]+',1,ROWNUM) s,COUNT(*) OVER() cnt
  FROM DUAL
CONNECT BY ROWNUM<=LENGTH(:s)-LENGTH(REPLACE(:s,','))+1
)
,t2 AS (
SELECT ROWNUM AS id, SUBSTR(SYS_CONNECT_BY_PATH(s,','),2) AS s2, LEVEL AS lvl
  FROM t
CONNECT BY s>PRIOR s AND LEVEL<cnt
)
,t3 AS (
SELECT id
      ,REGEXP_SUBSTR(s2,'[^,]+',1,rn) S3
  FROM t2
      ,(SELECT ROWNUM rn FROM DUAL CONNECT BY ROWNUM <=(SELECT MAX(cnt) FROM t))
WHERE t2.lvl>=rn     
)
,t4 AS (
SELECT id,MAX(SUBSTR(SYS_CONNECT_BY_PATH(s,','),2)) AS s4
  FROM (SELECT id,s,ROW_NUMBER() OVER(PARTITION BY id ORDER BY s) rn
          FROM (SELECT t2.id,t.s
                  FROM t,t2
                MINUS
                select id,s3 from t3
               )
       )
START WITH rn=1 CONNECT BY id = PRIOR id AND rn=PRIOR rn+1
GROUP BY id
)
select s2,s4
  FROM t2,t4
WHERE t2.id = t4.id;

使用道具 举报

回复
论坛徽章:
28
授权会员
日期:2009-01-04 22:12:21世界杯纪念徽章
日期:2014-07-14 11:31:462014年世界杯参赛球队: 澳大利亚
日期:2014-06-25 11:06:552014年新春福章
日期:2014-02-18 16:42:02ITPUB社区12周年站庆徽章
日期:2013-10-08 14:55:07NBA季后赛纪念徽章
日期:2013-06-21 14:52:05NBA常规赛纪念章
日期:2013-04-22 11:49:35季节之章:冬
日期:2012-11-15 16:55:18ITPUB元老
日期:2011-03-17 09:38:472014年世界杯参赛球队: 俄罗斯
日期:2014-07-17 17:21:42
30#
发表于 2010-4-9 23:22 | 只看该作者
好题目 体会高手的思路

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表