楼主: newkid

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

[复制链接]
论坛徽章:
40
授权会员
日期:2009-03-04 17:06:25最佳人气徽章
日期:2013-03-19 17:24:25SQL极客
日期:2013-12-09 14:13:35优秀写手
日期:2013-12-18 09:29:09ITPUB元老
日期:2015-03-04 13:33:34白羊座
日期:2016-03-11 13:49:34乌索普
日期:2017-11-17 11:40:00
31#
发表于 2010-4-9 23:23 | 只看该作者

回复 #29 newkid 的帖子

哈哈  等了半天大侠终于出手了
先好好看看学习下

使用道具 举报

回复
论坛徽章:
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
32#
 楼主| 发表于 2010-4-9 23:28 | 只看该作者
OO的#9和我的BITAND方法基本一样;
dingjun123的#15和我的TRANSLATE方法也很相似,jiqing1004在#19修改后就基本上一样了;
kmpx的#18一下没看懂;
kingtsi的#20很新颖,他先求出半个集合及其补集,然后反过来再UNION. 这个level<=(select count(rn)/2 from t)有时候能够提高很多效率的。

但是他的求补集方法不够严密:
(select wm_concat(x) from t where instr(m.p,','||x||',')=0)
如果X包含两个以上元素,这个WHERE就不成立了。

ocpdba591的#23用随机数产生组合,是不严密的做法。

[ 本帖最后由 newkid 于 2010-4-10 02:56 编辑 ]

使用道具 举报

回复
论坛徽章:
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
33#
 楼主| 发表于 2010-4-10 01:48 | 只看该作者
#18有很多重复的子查询,简化后变成这样:

with tmp as (select 'a,b,c' col from dual)
,t2 AS (select substr(col,rownum,1) col,rownum rn from (select replace(col,',') col from tmp) connect by rownum<=length(col))
,t3 AS (select distinct decode(a.col,b.col,a.col,c.col,a.col,a.col||decode(b.col,c.col,b.col,b.col||c.col)) col
        from t2 a,
             t2 b,
             t2 c
      where a.rn<=b.rn and a.rn<=c.rn and b.rn<=c.rn)
select decode(length(a.col),1,a.col,substr(a.col,0,1)||','||substr(a.col,2,1)) col,
       decode(length(b.col),1,b.col,substr(b.col,0,1)||','||substr(b.col,2,1)) col1
from t3 a,
     t3 b
where a.col not like '%'||b.col||'%' and b.col not like '%'||a.col||'%'
and length(a.col)<>length(b.col) and length(a.col)<>3 and length(b.col)<>3
;

这个t3的写法,最后加逗号的写法,求补集的写法,都只能针对三个元素,是非常不灵活的。

原题目链接:
http://asktom.oracle.com/pls/ask ... 2295214400346237735

里面用的是BITAND解法。

使用道具 举报

回复
论坛徽章:
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
34#
发表于 2010-4-10 07:55 | 只看该作者

使用道具 举报

回复
论坛徽章:
5
2010年世界杯参赛球队:意大利
日期:2010-03-23 15:18:272010年世界杯参赛球队:阿尔及利亚
日期:2010-05-23 13:13:032010广州亚运会纪念徽章:乒乓球
日期:2011-04-06 11:31:16
35#
发表于 2010-4-10 10:11 | 只看该作者
谢谢newkid大侠29#给出的方法还有32#的点评

32#你提到的
(select wm_concat(x) from t where instr(m.p,','||x||',')=0)
如果X包含两个以上元素,这个WHERE就不成立了。
可能是我没理解通还是,有点没看懂,split原始字符串后得到的每个元素分别存于t表列x中的每一行,只会有一个元素,不知道newkid大侠的意思是,我是不是理解错了你的意思?请指点,谢谢 ^_^

使用道具 举报

回复
论坛徽章:
2
2010新春纪念徽章
日期:2010-03-01 11:06:23优秀写手
日期:2014-02-09 06:00:12
36#
发表于 2010-4-10 10:37 | 只看该作者
准备抢注各种域名

asknewkid.net
asknewkid.com
asknewkid.com.cn
asknewkid.cn

使用道具 举报

回复
论坛徽章:
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
37#
 楼主| 发表于 2010-4-11 01:57 | 只看该作者
原帖由 kingtsi 于 2010-4-10 10:11 发表
谢谢newkid大侠29#给出的方法还有32#的点评

32#你提到的
(select wm_concat(x) from t where instr(m.p,','||x||',')=0)
如果X包含两个以上元素,这个WHERE就不成立了。
可能是我没理解通还是,有点没看懂,split原始字符串后得到的每个元素分别存于t表列x中的每一行,只会有一个元素,不知道newkid大侠的意思是,我是不是理解错了你的意思?请指点,谢谢 ^_^


哦,我看错了,确实X是单元素。
你的方法非常好!

借鉴一下:
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
      ,(SELECT WMSYS.WM_CONCAT(t.s) FROM t WHERE INSTR(','||s2||',',t.s)=0 ) AS COL2 ---- kingtsi的方法
  FROM t2;

[ 本帖最后由 newkid 于 2010-4-11 03:08 编辑 ]

使用道具 举报

回复
论坛徽章:
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
38#
 楼主| 发表于 2010-4-11 01:59 | 只看该作者
原帖由 CaptainKobe 于 2010-4-10 10:37 发表
准备抢注各种域名

asknewkid.net
asknewkid.com
asknewkid.com.cn
asknewkid.cn


咱还是有自知之明的! 就是一个老程序员在发挥余热而已。

使用道具 举报

回复
论坛徽章:
2
技术图书徽章
日期:2021-05-18 08:52:07
39#
发表于 2010-4-11 06:56 | 只看该作者
先好好看看学习下

使用道具 举报

回复
论坛徽章:
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
40#
 楼主| 发表于 2010-4-22 04:16 | 只看该作者
终于把11GR2折腾好了,第一件事就是玩玩这个递归的WITH子查询:

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


WITH t AS (
SELECT REGEXP_SUBSTR(:s,'[^,]+',1,ROWNUM) s
  FROM DUAL
CONNECT BY ROWNUM<=LENGTH(:s)-LENGTH(REPLACE(:s,','))+1
)
, T2(s,s1,s2) AS (
  SELECT s,s s1, REPLACE(','||:s||',',','||s||',',',') as s2
    FROM t
  UNION ALL
  SELECT t.s,t2.s1||','||t.s,REPLACE(','||t2.s2||',',','||t.s||',',',') as s2
    FROM t, T2
  WHERE t2.s<t.s
)
SELECT s1,TRIM(BOTH ',' FROM s2) FROM t2
WHERE TRIM(BOTH ',' FROM s2) IS NOT NULL;

它提供了逐层控制的功能,用REPLACE很方便地把新加入的字符从补集中剔除。

使用道具 举报

回复

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

本版积分规则 发表回复

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