楼主: huangzhiyun123

[PL/SQL] 请看下,这个SQL能写得出来就厉害啦

[复制链接]
论坛徽章:
0
11#
发表于 2017-5-25 17:03 | 只看该作者
0019最早的不是最后一条 2016/5/26 ?

使用道具 举报

回复
论坛徽章:
2
懒羊羊
日期:2015-03-04 14:52:112015年新春福章
日期:2015-03-06 11:58:18
12#
 楼主| 发表于 2017-5-25 17:14 | 只看该作者
bell6248 发表于 2017-5-25 16:46
是不是如下的意思

SQL> with t as

得到的结果是对的,但SQL好复杂哈。

使用道具 举报

回复
论坛徽章:
2
懒羊羊
日期:2015-03-04 14:52:112015年新春福章
日期:2015-03-06 11:58:18
13#
 楼主| 发表于 2017-5-25 17:15 | 只看该作者
chengccy2010 发表于 2017-5-25 16:58
AGENT_CODE ,RANK 组内的START_DATE为最小的记录?
SELECT *
FROM   (SELECT T.*,

不是,是agent_code分组,取最小的start_date但rank一样的,取较小的start_date

使用道具 举报

回复
论坛徽章:
18
优秀写手
日期:2014-02-27 06:00:13秀才
日期:2017-12-12 09:52:44秀才
日期:2017-08-11 15:37:32弗兰奇
日期:2017-07-04 09:16:01秀才
日期:2017-06-29 10:16:48乌索普
日期:2017-05-26 08:58:24娜美
日期:2017-05-18 16:07:23ITPUB15周年纪念
日期:2017-05-02 15:22:36妮可·罗宾
日期:2017-04-06 10:06:19处女座
日期:2016-03-10 09:03:26
14#
发表于 2017-5-25 17:49 | 只看该作者
huangzhiyun123 发表于 2017-5-25 17:15
不是,是agent_code分组,取最小的start_date但rank一样的,取较小的start_date

看懂了,类似连续的起点嘛。
model子句写法:
  1. SELECT * FROM
  2. (SELECT AGENT_CODE, RANK, START_DATE, END_DATE, S_START_DATE, RN1
  3. FROM   T
  4. MODEL
  5. PARTITION BY(AGENT_CODE)
  6. DIMENSION BY(ROW_NUMBER() OVER(PARTITION BY AGENT_CODE ORDER BY START_DATE) RN)
  7. MEASURES(RANK, START_DATE, END_DATE, START_DATE AS S_START_DATE, ROW_NUMBER() OVER(PARTITION BY AGENT_CODE ORDER BY START_DATE DESC) RN1)
  8. RULES(S_START_DATE [ RN ] =CASE WHEN RANK [CV()-1] IS NULL OR RANK [CV() - 1] <> RANK [ CV() ] THEN
  9.                               START_DATE [CV()]
  10.                            ELSE
  11.                               S_START_DATE [CV()-1]
  12.                            END))
  13.                            WHERE RN1=1
复制代码

使用道具 举报

回复
论坛徽章:
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
15#
发表于 2017-5-25 23:08 | 只看该作者
如果按照置顶帖提问的智慧来发帖,问题早解决了。

with t as
(
   select '142000394' AGENT_CODE, '0119' RANK,to_date('2017/3/1', 'yyyy/mm/dd') START_DATE, null END_DATE from dual
   union all
   select '142000394' AGENT_CODE, '0119' RANK,to_date('2017/1/1', 'yyyy/mm/dd') START_DATE, to_date('2017/2/28 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
   union all
   select '142000394' AGENT_CODE, '0122' RANK,to_date('2016/10/1', 'yyyy/mm/dd') START_DATE, to_date('2016/12/31 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
   union all
   select '142000394' AGENT_CODE, '0122' RANK,to_date('2016/5/31', 'yyyy/mm/dd') START_DATE, to_date('2016/9/30 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
  union all
  select '142000394' AGENT_CODE, '0119' RANK,to_date('2016/5/26', 'yyyy/mm/dd') START_DATE, to_date('2016/5/30 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
)
SELECT * FROM (
SELECT t2.*
      ,ROW_NUMBER() OVER(PARTITION BY AGENT_CODE ORDER BY START_DATE) rn
FROM   (SELECT T.*
               ,ROW_NUMBER() OVER(PARTITION BY AGENT_CODE, RANK ORDER BY START_DATE DESC) RN1
               ,ROW_NUMBER() OVER(PARTITION BY AGENT_CODE ORDER BY START_DATE DESC) RN2
         FROM   T
        ) t2
WHERE  RN1=RN2
)
WHERE rn=1

使用道具 举报

回复
论坛徽章:
18
优秀写手
日期:2014-02-27 06:00:13秀才
日期:2017-12-12 09:52:44秀才
日期:2017-08-11 15:37:32弗兰奇
日期:2017-07-04 09:16:01秀才
日期:2017-06-29 10:16:48乌索普
日期:2017-05-26 08:58:24娜美
日期:2017-05-18 16:07:23ITPUB15周年纪念
日期:2017-05-02 15:22:36妮可·罗宾
日期:2017-04-06 10:06:19处女座
日期:2016-03-10 09:03:26
16#
发表于 2017-5-26 09:41 | 只看该作者
newkid 发表于 2017-5-25 23:08
如果按照置顶帖提问的智慧来发帖,问题早解决了。

with t as

好思路,
由此想到了,用model的一次排序的写法,赶紧model还是蛮实用的
  1. SELECT * FROM
  2. (SELECT AGENT_CODE, RANK, START_DATE, END_DATE,RN1
  3. FROM   T
  4. MODEL
  5. PARTITION BY(AGENT_CODE)
  6. DIMENSION BY(ROW_NUMBER() OVER(PARTITION BY AGENT_CODE ORDER BY START_DATE DESC) RN)
  7. MEASURES(RANK, START_DATE, END_DATE, 0 AS RN1)
  8. RULES
  9. (
  10. RN1[ANY]=CASE WHEN RANK[CV()]=NVL(RANK[CV()-1],RANK[CV()]) AND RANK[CV()]=RANK[1] THEN 1 END,
  11. RN1[ANY]=CASE WHEN RN1[CV()+1] IS NULL AND RN1[CV()] =1 THEN 1 END
  12. ))
  13. WHERE RN1=1
复制代码

使用道具 举报

回复
论坛徽章:
18
优秀写手
日期:2014-02-27 06:00:13秀才
日期:2017-12-12 09:52:44秀才
日期:2017-08-11 15:37:32弗兰奇
日期:2017-07-04 09:16:01秀才
日期:2017-06-29 10:16:48乌索普
日期:2017-05-26 08:58:24娜美
日期:2017-05-18 16:07:23ITPUB15周年纪念
日期:2017-05-02 15:22:36妮可·罗宾
日期:2017-04-06 10:06:19处女座
日期:2016-03-10 09:03:26
17#
发表于 2017-5-26 10:10 | 只看该作者
chengccy2010 发表于 2017-5-26 09:41
好思路,
由此想到了,用model的一次排序的写法,赶紧model还是蛮实用的

测了下MODEL效率还没分析函数高

使用道具 举报

回复
论坛徽章:
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
18#
发表于 2017-5-26 10:23 来自手机 | 只看该作者
问题帖有个模木反就好了

使用道具 举报

回复
论坛徽章:
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
19#
发表于 2017-5-26 22:05 | 只看该作者
chengccy2010 发表于 2017-5-26 10:10
测了下MODEL效率还没分析函数高

MODEL的效率比不上纯SQL和PL/SQL。而且ORACLE在10G之后就没有做过任何改进,看来是要让它自生自灭了。

使用道具 举报

回复
论坛徽章:
1
秀才
日期:2016-11-25 16:52:36
20#
发表于 2017-5-27 14:44 | 只看该作者
with t as
(
   select '142000394' AGENT_CODE, '0119' RANK,to_date('2017/3/1', 'yyyy/mm/dd') START_DATE, null END_DATE from dual
   union all
   select '142000394' AGENT_CODE, '0119' RANK,to_date('2017/1/1', 'yyyy/mm/dd') START_DATE, to_date('2017/2/28 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
   union all
   select '142000394' AGENT_CODE, '0122' RANK,to_date('2016/10/1', 'yyyy/mm/dd') START_DATE, to_date('2016/12/31 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
   union all
   select '142000394' AGENT_CODE, '0122' RANK,to_date('2016/5/31', 'yyyy/mm/dd') START_DATE, to_date('2016/9/30 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
  union all
  select '142000394' AGENT_CODE, '0119' RANK,to_date('2016/5/26', 'yyyy/mm/dd') START_DATE, to_date('2016/5/30 23:59:59', 'yyyy/mm/dd hh24:mi:ss') END_DATE from dual
)
SELECT *
  FROM (SELECT t2.*,
               row_number() OVER(PARTITION BY AGENT_CODE ORDER BY START_DATE DESC) rn
          FROM (SELECT t.*,
                       lead(t.RANK) over(PARTITION BY AGENT_CODE ORDER BY START_DATE DESC) lead_rank
                  FROM t) t2
         WHERE t2.rank <> nvl(t2.lead_rank, t2.rank || '*'))
WHERE rn = 1

使用道具 举报

回复

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

本版积分规则 发表回复

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