查看: 8443|回复: 17

[精华] 回复 wangfans 高难度sql,喜欢研究SQL算法的进

[复制链接]
论坛徽章:
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
跳转到指定楼层
1#
发表于 2008-3-6 22:52 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
回复 http://www.itpub.net/viewthread.php?tid=949571&page=1
原帖问题由   wangfans   发布:

高难度sql,喜欢研究SQL算法的进


SQL> select * from test3;

        ID      VALUE      POWER
---------- ---------- ----------
         1          2          3
         2          1          2
         3          4          4
         4          5          2
         5          4          3
        

ID为主键,value代表值,power代表权值。

要求:

求出所有值乘以比相应权值小的整数之积为16的权值组合。

例如:
假如test3的所有数据如上,则

2*1+1*1+4*1+5*1+4*1=16(这里权值组合为  1,1,1,1)
2*1+1*1+4*0+5*1+4*2=16(这里权值组合为  1,1,0,1,2)


练了一下手(有点成就感,所以开了新帖   ):
以下测试环境 Oracle 10G
create table t(id number,value number,power number);
insert into T values (1, 2, 3);
insert into T values (2, 1, 2);
insert into T values (3, 4, 4);
insert into T values (4, 5, 2);
insert into T values (5, 4, 3);
commit;
with tmp as
(
  select level lev, sys_connect_by_path(value || '*' || rn, '+') powers, value * rn val
    from (select id,value,rn
             from t, (select rownum - 1 rn from t) a
            start with rn = 0
           connect by prior id = id
                  and rn = prior rn + 1
                  and rn < power)
   start with id = 1
  connect by id = prior id + 1
)
select ltrim(a.powers, '+') powers
  from tmp a, tmp b
where a.powers || '+'  like b.powers || '+%'
   and a.lev = (select count(1) from t)
group by a.powers
having sum(b.val) = 16;

POWERS
----------------------
2*2+1*0+4*1+5*0+4*2
2*0+1*0+4*2+5*0+4*2
2*0+1*0+4*3+5*0+4*1
2*2+1*0+4*2+5*0+4*1
2*2+1*0+4*3+5*0+4*0
2*1+1*1+4*0+5*1+4*2
2*1+1*1+4*1+5*1+4*1
2*1+1*1+4*2+5*1+4*0

8 rows selected

SQL>

不过这个SQL要完成这个功能, 还需要对数据有个限制, 就是 ID 字段的值是从 1 开始连续不断的.
以上SQL在10G环境中运行通过. 此 SQL 也没使用到 10G 的什么新特性, 但是跑到 9i 环境中运行失败.

在考虑 ID 字段值不是 从 1 开始并连续的情况下, 内嵌一个 SQL 查询来自行生成一个 连续的 ID 时有些问题.

不断的尝试SQL写法, 终于发现一种可以解决ID字段不是从1开始并连续的问题了. 如下:
with tmp as
(
  select level lev, sys_connect_by_path(value || '*' || rn, '+') powers, value * rn val
    from (select idx, value, rn
             from (select rn, t.id, idx, value, power
                      from t, (select rownum - 1 rn from t) a, (select rownum idx, id from t) b
                     where t.id = b.id)
            start with rn = 0
           connect by prior id = id
                  and rn = prior rn + 1
                  and rn < power)
   start with idx = 1
  connect by idx = prior idx + 1
)
select ltrim(a.powers, '+') powers
  from tmp a, tmp b
where a.powers || '+' like b.powers || '+%'
   and a.lev = (select count(1) from t)
group by a.powers
having sum(b.val) = 16;

[ 本帖最后由 nyfor 于 2008-3-7 08:51 编辑 ]
论坛徽章:
281
2015年新春福章
日期:2015-03-06 11:57:312012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-01-04 11:51:22蛋疼蛋
日期:2011-12-29 07:37:22迷宫蛋
日期:2011-12-26 14:19:41茶鸡蛋
日期:2011-11-17 09:20:52茶鸡蛋
日期:2011-11-10 22:42:38ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15茶鸡蛋
日期:2011-10-24 09:48:48ITPUB十周年纪念徽章
日期:2011-09-27 16:30:47
2#
发表于 2008-3-7 09:13 | 只看该作者

使用道具 举报

回复
论坛徽章:
44
双鱼座
日期:2016-01-07 20:57:31奔驰
日期:2013-08-02 22:22:552013年新春福章
日期:2013-02-25 14:51:24迷宫蛋
日期:2013-01-29 22:12:11蛋疼蛋
日期:2013-01-07 15:50:53ITPUB十周年纪念徽章
日期:2011-11-01 16:20:28紫蛋头
日期:2011-07-31 11:27:01蜘蛛蛋
日期:2011-06-14 14:20:33蛋疼蛋
日期:2011-06-03 19:39:27SQL大赛参与纪念
日期:2011-04-13 12:08:17
3#
发表于 2008-3-7 09:17 | 只看该作者
牛人!

使用道具 举报

回复
论坛徽章:
7
生肖徽章:猪
日期:2007-09-26 17:09:50ITPUB元老
日期:2010-04-29 22:07:05
4#
发表于 2008-3-7 09:44 | 只看该作者
想学习,可惜有点看不懂!!

使用道具 举报

回复
论坛徽章:
1
优秀写手
日期:2014-06-21 06:00:12
5#
发表于 2008-3-7 10:03 | 只看该作者
看不懂啊,哪位牛人解释解释

使用道具 举报

回复
论坛徽章:
66
现任管理团队成员
日期:2011-05-07 01:45:08版主9段
日期:2013-04-21 02:21:02ITPUB年度最佳版主
日期:2014-02-19 10:05:27ITPUB年度最佳版主
日期:2013-01-30 17:30:25ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05优秀写手
日期:2013-12-18 09:29:15元宝章
日期:2015-02-10 19:57:54金牌徽章
日期:2015-02-10 19:59:42银牌徽章
日期:2015-02-10 19:59:42铜牌徽章
日期:2015-02-10 19:59:41
6#
发表于 2008-3-7 17:28 | 只看该作者
sys_connect_by_path这个函数好像9I不支持,9i以上才可以

使用道具 举报

回复
论坛徽章:
85
2008新春纪念徽章
日期:2008-02-13 12:43:03双黄蛋
日期:2011-06-17 11:07:502011新春纪念徽章
日期:2011-02-18 11:42:472011新春纪念徽章
日期:2011-01-04 10:24:022010年世界杯参赛球队:荷兰
日期:2010-08-28 00:09:112010年世界杯参赛球队:科特迪瓦
日期:2010-03-02 12:36:542010新春纪念徽章
日期:2010-03-01 11:07:242010新春纪念徽章
日期:2010-03-01 11:07:242010新春纪念徽章
日期:2010-01-04 08:33:082010年世界杯参赛球队:意大利
日期:2009-12-31 14:41:24
7#
发表于 2008-3-7 17:37 | 只看该作者
就是穷举法,如果数字增大,速度就很慢了

使用道具 举报

回复
论坛徽章:
226
BLOG每日发帖之星
日期:2010-02-11 01:01:06紫蛋头
日期:2013-01-12 23:45:222013年新春福章
日期:2013-02-25 14:51:24问答徽章
日期:2013-10-17 18:06:40优秀写手
日期:2013-12-18 09:29:10马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14马上有钱
日期:2014-02-19 11:55:14马上有对象
日期:2014-02-19 11:55:14马上加薪
日期:2014-02-19 11:55:14
8#
发表于 2008-3-7 17:39 | 只看该作者
原帖由 wangfans 于 2008-3-7 17:28 发表
sys_connect_by_path这个函数好像9I不支持,9i以上才可以



9i支持

使用道具 举报

回复
论坛徽章:
66
现任管理团队成员
日期:2011-05-07 01:45:08版主9段
日期:2013-04-21 02:21:02ITPUB年度最佳版主
日期:2014-02-19 10:05:27ITPUB年度最佳版主
日期:2013-01-30 17:30:25ITPUB年度最佳技术原创精华奖
日期:2012-03-13 17:12:05优秀写手
日期:2013-12-18 09:29:15元宝章
日期:2015-02-10 19:57:54金牌徽章
日期:2015-02-10 19:59:42银牌徽章
日期:2015-02-10 19:59:42铜牌徽章
日期:2015-02-10 19:59:41
9#
发表于 2008-3-7 17:45 | 只看该作者
恩,刚试验了下,可以用。没有看完NYFOR的帖子就乱猜了,猜错了,呵呵。

[ 本帖最后由 wangfans 于 2008-3-7 17:53 编辑 ]

使用道具 举报

回复
论坛徽章:
5
奥运会纪念徽章:摔跤
日期:2008-07-02 08:48:392009日食纪念
日期:2009-07-22 09:30:00优秀写手
日期:2013-12-18 09:29:11SQL数据库编程大师
日期:2016-01-13 10:30:43SQL大赛参与纪念
日期:2016-01-13 10:32:19
10#
发表于 2008-5-26 00:31 | 只看该作者
MS 9i下
sys_connect_by_path的第一个参数不支持表达式

使用道具 举报

回复

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

本版积分规则 发表回复

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