楼主: newkid

[精华] SQL解惑(第2版) 的一些样题

[复制链接]
论坛徽章:
9
2009日食纪念
日期:2009-07-22 09:30:00ITPUB8周年纪念徽章
日期:2009-09-27 10:21:21祖国60周年纪念徽章
日期:2009-10-09 08:28:002010新春纪念徽章
日期:2010-03-01 11:19:10ITPUB9周年纪念徽章
日期:2010-10-08 09:31:22ITPUB十周年纪念徽章
日期:2011-11-01 16:23:262012新春纪念徽章
日期:2012-01-04 11:53:54ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:152013年新春福章
日期:2013-02-25 14:51:24
81#
发表于 2012-10-15 14:01 | 只看该作者
呵呵, newkids 兄厉害。

使用道具 举报

回复
论坛徽章:
9
2009日食纪念
日期:2009-07-22 09:30:00ITPUB8周年纪念徽章
日期:2009-09-27 10:21:21祖国60周年纪念徽章
日期:2009-10-09 08:28:002010新春纪念徽章
日期:2010-03-01 11:19:10ITPUB9周年纪念徽章
日期:2010-10-08 09:31:22ITPUB十周年纪念徽章
日期:2011-11-01 16:23:262012新春纪念徽章
日期:2012-01-04 11:53:54ITPUB 11周年纪念徽章
日期:2012-10-09 18:08:152013年新春福章
日期:2013-02-25 14:51:24
82#
发表于 2012-10-18 19:03 | 只看该作者
谜题 59 解答得很巧妙。
joe celko在 《thinking in set》(sql沉思录)里提到另一个解法也很巧妙:

select task_id, min_start_date,max(end_date)
from (
select task_id
      , start_date
      , max( case when start_date > max_end_date then start_date end)  ---这一步找到离自己最近的broken
                 over ( partition by task_id order by start_date,end_date
                            rows between unbounded preceding and current row ) as min_start_date
       ,end_date from (
select task_id
      ,start_date
      ,end_date
      ,coalesce(max(end_date)
           over ( partition by task_id order by start_date,end_date
                   rows between unbounded preceding and 1 preceding )
                   , start_date -2 days) as max_end_date
      from timesheets ) )
group by task_id,min_start_date


谜题 27 我想到一个SQL可以减少表的关联,
貌似结果也是对的:
WITH T(SNO,PNO,CNT)
     AS (SELECT SUPPARTS.*,
                COUNT(PNO)
                  OVER(PARTITION BY SNO ) AS CNT
         FROM   SUPPARTS)
SELECT   A.SNO,
         B.SNO
FROM     T A,
         T B
WHERE    A.PNO = B.PNO
         AND A.SNO < B.SNO
         AND A.CNT = B.CNT
GROUP BY A.SNO,B.SNO
HAVING   COUNT(* ) = MAX(A.CNT);

使用道具 举报

回复
论坛徽章:
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
83#
 楼主| 发表于 2012-10-19 03:20 | 只看该作者
mdkii 发表于 2012-10-18 19:03
谜题 59 解答得很巧妙。
joe celko在 《thinking in set》(sql沉思录)里提到另一个解法也很巧妙:

很不错的写法!59题的找断点方法和我一样; 27题用分析函数进一步减少了连接次数。

使用道具 举报

回复
论坛徽章:
41
2010广州亚运会纪念徽章:橄榄球
日期:2011-01-11 06:17:26红孩儿
日期:2012-12-19 11:07:13玉石琵琶
日期:2012-12-19 11:07:13九尾狐狸
日期:2012-12-19 11:07:13嫦娥
日期:2012-12-19 11:07:13玉兔
日期:2012-12-19 11:07:13紫蜘蛛
日期:2012-12-19 11:07:13蓝色妖姬
日期:2012-12-19 11:07:13紫蛋头
日期:2013-01-23 09:04:49SQL大赛参与纪念
日期:2013-12-06 14:03:45
84#
发表于 2012-10-19 07:21 | 只看该作者
---For #59
select start_date, max(end_date) end_date from  (select * from (select a.*, rownum rn from Timesheets a order by start_date)
model
dimension by (rn)
measures(start_date, end_date)
rules ( start_date[rn>1]= case when end_date[cv()-1] >= start_date[cv()] then start_date[cv()-1] else start_date[cv()] end))
group by start_date;

---For #27
with t0 as (select sno, rtrim(xmlagg(xmlelement (e, pno || ',') order by pno).extract ('//text()'),',') pnos
from    supparts group by    sno )
select rtrim (xmlagg (xmlelement (e, sno || '=') order by sno).extract ('//text()'), '=')  equal_sets
from t0 group by pnos having count(*) >=2;

使用道具 举报

回复
论坛徽章:
1
优秀写手
日期:2014-01-23 06:00:12
85#
发表于 2012-10-19 09:58 | 只看该作者
好东西,收藏了

使用道具 举报

回复
论坛徽章:
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
86#
 楼主| 发表于 2012-10-20 03:11 | 只看该作者
xqmei 发表于 2012-10-19 07:21
---For #59
select start_date, max(end_date) end_date from  (select * from (select a.*, rownum rn fr ...

#59:
断点判断的原理不变,但你的MODEL只和上一行相比,所以有点漏洞。比如我构造下面的数据:

DELETE TIMESHEETS;

--- 第一行有一整年时间,包含了所有其他区间,合并结果应该是这一行
INSERT INTO TIMESHEETS VALUES (1,  DATE '1997-01-01', DATE '1997-12-31');
INSERT INTO TIMESHEETS VALUES (2,  DATE '1997-02-01', DATE '1997-2-1');
INSERT INTO TIMESHEETS VALUES (3,  DATE '1997-03-01', DATE '1997-3-1');

用你的MODEL返回错误结果:
select start_date, max(end_date) end_date from  (select * from (select a.*, rownum rn from Timesheets a order by start_date)
model
dimension by (rn)
measures(start_date, end_date)
rules ( start_date[rn>1]= case when end_date[cv()-1] >= start_date[cv()] then start_date[cv()-1] else start_date[cv()] end))
group by start_date;

START_DATE          END_DATE
------------------- -------------------
1997-01-01 00:00:00 1997-12-31 00:00:00
1997-03-01 00:00:00 1997-03-01 00:00:00

#27
XML很强大,但如天书一般,幸亏咱们现在有了LISTAGG, 我把它翻译过来:
SELECT LISTAGG(sno,'=') WITHIN GROUP (ORDER BY sno)
  FROM (SELECT sno,LISTAGG(pno,',') WITHIN GROUP(ORDER BY pno) pnos FROM supparts GROUP BY sno)
GROUP BY pnos
HAVING COUNT(*)>=2;

使用道具 举报

回复
论坛徽章:
41
2010广州亚运会纪念徽章:橄榄球
日期:2011-01-11 06:17:26红孩儿
日期:2012-12-19 11:07:13玉石琵琶
日期:2012-12-19 11:07:13九尾狐狸
日期:2012-12-19 11:07:13嫦娥
日期:2012-12-19 11:07:13玉兔
日期:2012-12-19 11:07:13紫蜘蛛
日期:2012-12-19 11:07:13蓝色妖姬
日期:2012-12-19 11:07:13紫蛋头
日期:2013-01-23 09:04:49SQL大赛参与纪念
日期:2013-12-06 14:03:45
87#
发表于 2012-10-20 04:18 | 只看该作者
For #59, how about this?

select start_date, max(end_date) from  ( select distinct start_date, end_date from
(select a.*, rownum rn from Timesheets a order by start_date)
model dimension by (rn) measures(start_date, end_date) rules (
end_date[rn>1]= case when end_date[cv()-1] >= start_date[cv()]  then greatest(end_date[cv()-1],end_date[cv()]) else end_date[cv()] end,
start_date[rn>1]= case when end_date[cv()-1] >= start_date[cv()]  then least(start_date[cv()-1],start_date[cv()]) else start_date[cv()] end
) ) group by start_date;

使用道具 举报

回复
论坛徽章:
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
88#
 楼主| 发表于 2012-10-20 05:28 | 只看该作者
改了就对了,但是least(start_date[cv()-1],start_date[cv()])没有必要因为你已经按start_date排序,还是用原来的start_date[cv()-1] .

使用道具 举报

回复
论坛徽章:
6
祖国60周年纪念徽章
日期:2009-10-09 08:28:002010年世界杯参赛球队:阿尔及利亚
日期:2010-06-19 23:30:06ITPUB9周年纪念徽章
日期:2010-10-08 09:31:212010广州亚运会纪念徽章:篮球
日期:2011-02-10 14:31:35参与SAP云计算之旅活动纪念
日期:2011-05-17 13:35:452012新春纪念徽章
日期:2012-01-04 11:54:26
89#
发表于 2012-10-22 15:02 | 只看该作者
学习了,多谢~

使用道具 举报

回复
论坛徽章:
9
2013年新春福章
日期:2013-02-25 14:51:24迷宫蛋
日期:2013-06-25 16:00:282014年新春福章
日期:2014-02-18 16:44:08马上有对象
日期:2014-02-18 16:44:082014年世界杯参赛球队: 比利时
日期:2014-06-13 11:32:272015年新春福章
日期:2015-03-04 14:53:162015年新春福章
日期:2015-03-06 11:58:39水瓶座
日期:2016-01-31 20:21:28技术图书徽章
日期:2017-02-24 09:11:04
90#
发表于 2012-10-23 16:40 | 只看该作者
神贴收藏。

使用道具 举报

回复

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

本版积分规则 发表回复

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