12
返回列表 发新帖
楼主: newkid

[每日一题] 趣味SQL: 力扣218. 天际线问题

[复制链接]
论坛徽章:
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
11#
 楼主| 发表于 2024-9-22 06:45 | 只看该作者


暴力法:用连接,检查每个建筑物的起点终点上,找到这些点上面存在的最高的建筑物高度。如果连续多个点的高度不变,输出的时候要合并,只输出第一个。
with b as ( ---- 每个建筑物拆开成起点和终点两行数据
select distinct case when flag='START' then start_pos else end_pos end as pos
  from buildings cross join (select 'START' flag from dual union all select 'END' from dual)
)
select min(pos) as pos
      ,h2
  from (
        select pos
              ,h2
               ,row_number() over(order by pos) rn1
               ,row_number() over(partition by h2 order by pos) rn2
          from (
                select b.pos
                      ,nvl(max(b2.height),0) h2
                  from b left join buildings b2
                       on b.pos>=b2.start_pos and b.pos<b2.end_pos
                  group by b.pos
               )
        )
group by rn1-rn2,h2
order by 1;

也可以用标量子查询代替自连接:
with b as (
select distinct case when flag='START' then start_pos else end_pos end as pos
  from buildings cross join (select 'START' flag from dual union all select 'END' from dual)
)
select min(pos) as pos
      ,h2
  from (
        select pos
              ,h2
               ,row_number() over(order by pos) rn1
               ,row_number() over(partition by h2 order by pos) rn2
          from (
                select b.pos
                      ,nvl((select max(height) from buildings b2 where b2.start_pos<=b.pos and b2.end_pos>b.pos),0) h2
                  from b
               )
        )
group by rn1-rn2,h2
order by 1;

      POS         H2
--------- ----------
        2         10
        3         15
        7         12
       12          0
       15         10
       20          8
       24          0



7 rows selected.

--------match recognize: 依然是检查每个起点终点(记为strt),和它之后出现的每个建筑物终点end_p进行匹配(之后出现的起点不会影响轮廓线,不用理会), 如果这个end_p的起点在strt之前就取其高度。
with b as ( ---- 每个建筑物拆开成起点和终点两行数据
select buildings.*
      ,case when flag='START' then start_pos else end_pos end as pos
      ,flag
  from buildings cross join (select 'START' flag from dual union all select 'END' from dual)
)
,b2 as (
select * from b
     match_recognize (
     order by pos
     measures
        strt.pos as pos
       ,final max(end_p.height) as h2
     one row per match
     after match skip to next row  ----- 一个strt匹配结束之后跳到下一个点
     pattern( strt (end_p | other_p)*)
     define end_p as flag='END' and pos>strt.pos and start_pos<=strt.pos
     )
)
select pos,nvl(h2,0) as h2   ---如果多个点有同样高度,去重复
  from b2
     match_recognize (
     order by pos
     measures
          first(pos) as pos
         ,first(h2) as h2        
     one row per match
     pattern( strt dup*)
     define dup as h2 = prev(h2)
     )
;

       POS         H2
---------- ----------
         2         10
         3         15
         7         12
        12          0
        15         10
        20          8
        24          0

7 rows selected.

使用道具 举报

回复
论坛徽章:
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
12#
发表于 2024-9-22 07:32 | 只看该作者
newkid 发表于 2024-9-22 06:45
暴力法:用连接,检查每个建筑物的起点终点上,找到这些点上面存在的最高的建筑物高度。如果连续多个点的高 ...

你的第一种

Run Time (s): real 2.395 user 4.578125 sys 0.093750
第二种
Run Time (s): real 4.094 user 4.046875 sys 0.000000
我的
Run Time (s): real 5.333 user 10.046875 sys 0.015625

使用道具 举报

回复
论坛徽章:
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
13#
发表于 2024-9-22 07:34 | 只看该作者
bu.rar (69.05 KB, 下载次数: 6) 测试数据

使用道具 举报

回复
论坛徽章:
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
14#
 楼主| 发表于 2024-9-22 08:15 | 只看该作者
〇〇 发表于 2024-9-22 07:32
你的第一种 Run Time (s): real 2.395 user 4.578125 sys 0.093750第二种Run Time (s): real 4.094 user 4. ...

什么库?match_recognize 也支持?

使用道具 举报

回复
论坛徽章:
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
15#
发表于 2024-9-22 13:28 | 只看该作者
newkid 发表于 2024-9-22 08:15
什么库?match_recognize 也支持?

duckdb,不支持match_recognize

使用道具 举报

回复

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

本版积分规则 发表回复

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