`
liaobinxu
  • 浏览: 43564 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

sql解惑-麻醉师问题

SQL 
阅读更多
问题:Leonard C.Medal在许多年前提出了很多了这个技巧问题。 在医院的手术室中, 麻醉师为手术中的病人实行麻醉。 每个人麻醉过程的信息都记录在一个表中。
[list]
引用
procs
proc_id           anest_name        start_time        end_time
----------------------------------------------------------------------------
10                    'Baker'                 08:00               11:00
20                    'Baker'                 09:00                13:00
30                    'Dow'                   09:00                15:30
40                    'Dow'                   08:00                13:30
50                    'Dow'                  10:00                 11:30
60                    'Dow'                  12:30                 13:30
70                    'Dow'                  13:30                 14:30
80                    'Dow'                  18:00                 19:00

注意抹嘴是的某些时间是重叠的, 这不是错误。 麻醉师跟外科医生不同, 他可以在手术过程中从一个手术室走到另一个手术室,依次检查每一个病人, 调整药的计量, 留下实习医生和护士时刻监察病人的情况。

麻醉师的工资按照麻醉过程数量支付, 但是计算方法很复杂。 根据麻醉师同时负责的麻醉过程的最大数量, 为每个麻醉过程二支付给麻醉师的报酬是浮动的。 麻醉工程越多, 为每个过程支付的报酬就越少。

问题就成为对于每一个人进行中的麻醉过程, 确定每一个麻醉师同时进行麻醉过程的最大即时数目。
我们通过可以通过图形到处答案,以便更好的理解问题。
proc_id     max_inst_count
------------------------------------------------
10            2
20           2
30            3
40            3
50            3
60            3
70            2
80            1


--创建一个sequence proc_sequence
create sequence proc_sequence
increment by 10
start with 10
nomaxvalue
nocycle
noorder;
--创建一个procs表
 create table procs(
        proc_id integer not null primary key,
        anest_name  varchar2(40) not null,
        start_time date not null,
        end_time date not null
 );

向procs表插入数据

--     PROC_ID ANEST_NAME                               START_TIME  END_TIME
--------------------------------------- ---------------------------------------- ----------- -----------
--     10 'Baker'                                     08:00:00                       11:00:00
--     20 'Baker'                                     09:00:00                       13:00:00
--     30 'Dow'                                       09:00:00                       15:30:00
--     40 'Dow'                                       08:00:00                       13:30:00
--     50 'Dow'                                       10:00:00                       11:30:00
--     60 'Dow'                                       12:30:00                       13:30:00
--     70 'Dow'                                       13:30:00                       14:30:00
--     80 'Dow'                                       18:00:00                       19:30:00

insert into procs values(
proc_sequence.nextval,'Baker',to_date('2009-3-22 08:00','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 11:00','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Baker',to_date('2009-3-22 09:00','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 13:00','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Dow',to_date('2009-3-22 09:00','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 15:30','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Dow',to_date('2009-3-22 08:00','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 13:30','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Dow',to_date('2009-3-22 10:00','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 11:30','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Dow',to_date('2009-3-22 12:30','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 13:30','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Dow',to_date('2009-3-22 13:30','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 14:30','yyyy-mm-dd hh24:mi'));
insert into procs values(
proc_sequence.nextval,'Dow',to_date('2009-3-22 18:00','yyyy-mm-dd hh24:mi'),
to_date('2009-3-22 19:30','yyyy-mm-dd hh24:mi'));

--方法1
如果显示权限不足, 请登入sys账号,并以as sysdba方式登录 然后授权view给scott // grant create view to scott;
create view Events (proc_id,comparison_proc, anest_name,event_time,event_type)           
as
select  p1.proc_id,p2.proc_id,p1.anest_name,p2.start_time,+1 from procs p1, procs p2      
where p1.anest_name=p2.anest_name                                                                                 
union
select p1.proc_id, p2.proc_id, p1.anest_name,p2.end_time,-1 from procs p1, procs p2
where p1.anest_name=p2.anest_name
and not (p2.end_time<=p1.start_time or p2.start_time>=p1.end_time);

说明:用数学知识:not ((p2.end_time<=p1.start_time or p2.start_time>=p1.end_time) )等价于 p2.end_time>p1.start_time and p2.start_time <p1.end_time,意思是p2
--的时间段在p1的时间段的真子集(不包括两端)
方法2
select p3.proc_id , max(ConcurrentProcs.tally)
from (select p1.anest_name  anest_name, p1.start_time start_time, count(*) tally
     from procs p1
     inner join  procs p2
     on p1.anest_name=p2.anest_name
     and p2.start_time<=p1.start_time
     and p2.end_time>p1.start_time
     group by p1.anest_name, p1.start_time
)ConcurrentProcs--(anest_name,start_time, tally)
  inner join
  procs p3
  on ConcurrentProcs.anest_name=p3.anest_name
  and p3.start_time<=ConcurrentProcs.start_time
  and p3.end_time> ConcurrentProcs.start_time
  group by p3.proc_id


结果      
                        PROC_ID MAX(CONCURRENTPROCS.TALLY)
--------------------------------------- --------------------------
                                     30                          3
                                     20                          2
                                     70                          2
                                     40                          3
                                     50                          3
                                     80                          1
                                     10                          2
                                     60                          3


解析上面这个复杂的查询
首先查看它的子查询, 分为几步
step 1
select p1.anest_name , to_char(p1.start_time,'hh24:mi:ss'), count(*)
     from procs p1
     inner join  procs p2
     on p1.anest_name=p2.anest_name
     and p2.start_time<=p1.start_time
     and p2.end_time>p1.start_time
     group by p1.anest_name, p1.start_time;

结果是
ANEST_NAME                               TO_CHAR(P1.START_TIME,'HH24:MI   COUNT(*)
---------------------------------------- ------------------------------ ----------
Baker                                    09:00:00                                2
Dow                                      13:30:00                                2
Dow                                      08:00:00                                1
Dow                                      12:30:00                                3
Dow                                      10:00:00                                3
Baker                                    08:00:00                                1
Dow                                      09:00:00                                2
Dow                                      18:00:00                                1

step 2
对step 1 的查询在进行分解
select p1.proc_id P1ID,p2.proc_id P2ID,p1.anest_name P1ANEST_NAME ,
  to_char(P2.start_time,'hh24:mi:ss') P2ST,
  to_char(p1.start_time,'hh24:mi:ss') P1ST,
  to_char(p2.end_time,'hh24:mi:ss') P2ET
     from procs p1
     inner join  procs p2
     on p1.anest_name=p2.anest_name
     and p2.start_time<=p1.start_time
     and p2.end_time>p1.start_time order by p1.proc_id

    
得到的查询结果
                                   P1ID                                    P2ID P1ANEST_NAME                             P2ST     P1ST     P2ET
--------------------------------------- --------------------------------------- ---------------------------------------- -------- -------- --------
                                     10                                      10 Baker                                    08:00:00 08:00:00 11:00:00
                                     20                                      10 Baker                                    08:00:00 09:00:00 11:00:00
                                     20                                      20 Baker                                    09:00:00 09:00:00 13:00:00
                                    30                                      30 Dow                                      09:00:00 09:00:00 15:30:00
                                     30                                      40 Dow                                      08:00:00 09:00:00 13:30:00
                                    40                                      40 Dow                                      08:00:00 08:00:00 13:30:00
                                     50                                      50 Dow                                      10:00:00 10:00:00 11:30:00
                                     50                                      40 Dow                                      08:00:00 10:00:00 13:30:00
                                     50                                      30 Dow                                      09:00:00 10:00:00 15:30:00
                                     60                                      30 Dow                                      09:00:00 12:30:00 15:30:00
                                     60                                      40 Dow                                      08:00:00 12:30:00 13:30:00
                                    60                                      60 Dow                                      12:30:00 12:30:00 13:30:00
                                     70                                      70 Dow                                      13:30:00 13:30:00 14:30:00                                     70                                      30 Dow                                      09:00:00 13:30:00 15:30:00
                                     80                                      80 Dow                                      18:00:00 18:00:00 19:30:00

得到一个结论: 就是在同意麻醉师的情况下, 找到一组其中p1的启动时间在p2在开始之后(包括开始时刻)、在p2结束之前,这样的到的结果p1就是和其他麻醉记录(包括自己)有交集的。然后在在一proc_id,anest_name 分组,就可以得到和其他记录有时间相交的记录(但是并不是相交记录的最大数目)
step 3
select p3.proc_id , max(ConcurrentProcs.tally)
from (select p1.anest_name  anest_name, p1.start_time start_time, count(*) tally
     from procs p1
     inner join  procs p2
     on p1.anest_name=p2.anest_name
     and p2.start_time<=p1.start_time
     and p2.end_time>p1.start_time
     group by p1.anest_name, p1.start_time
)ConcurrentProcs--(anest_name,start_time, tally)
  inner join
  procs p3
  on ConcurrentProcs.anest_name=p3.anest_name
  and p3.start_time<=ConcurrentProcs.start_time
  and p3.end_time> ConcurrentProcs.start_time
  group by p3.proc_id

结果    
                         PROC_ID MAX(CONCURRENTPROCS.TALLY)
--------------------------------------- --------------------------
                                     30                          3
                                     20                          2
                                     70                          2
                                     40                          3
                                     50                          3
                                     80                          1
                                     10                          2
                                     60                          3

结论: step 2中找到的集合p1的就是step 3的视图ConcurrentProcs,而p3.start_time<=ConcurrentProcs.start_time and p3.end_time> ConcurrentProcs.start_time这两个条件表示找到一个集合p3能够在p1发生和p1结束之前发生(p1和任何记录都有时间交集的麻醉记录),等价于和任何都有交集的集合有相交的集合的条件下,取相交数量的最大值, 就是确定每一个麻醉师同时进行麻醉过程的最大即时数目


方法3
想法是在所有的麻醉记录过程中(p1)进行循环;对于每一个麻醉过程p1, 查找其起始时间落在麻醉过程p1中的麻醉过程p2. 对于找到的每一个p2的起始时间,计算该时间正在进行的麻醉过程(p3)的数目。然后,去出麻醉过程p1的最大计数。
create view Vprocs(id1,id2,total)
as
select p1.proc_id,p2.proc_id,count(*) from procs p1, procs p2, procs p3
where p2.anest_name=p1.anest_name
and p3.anest_name=p1.anest_name
and p1.start_time<=p2.start_time
and p1.start_time<p2.end_time
and p3.start_time<p2.start_time
and p2.start_time<p3.end_time
group by p1.proc_id,p2.proc_id;

然后对每一过程取最大值:
select id1 proc_id, max(total) max_inst_count from Vprocs group by id1;
结果是
                                PROC_ID MAX_INST_COUNT
--------------------------------------- --------------
                                     30              2
                                     70              1
                                     20              1
                                     50              2
                                     40              2
                                     60              2
                                     10              1

共有七项记录

结果有问题: 应该选取八项:
0
0
分享到:
评论

相关推荐

    sql解惑-跟踪投资组合问题

    标题中的“sql解惑-跟踪投资组合问题”指的是在数据库管理中,特别是在SQL查询中解决与投资组合管理相关的复杂问题。投资组合问题通常涉及到金融数据分析,包括股票、债券和其他金融资产的投资组合表现、风险评估...

    sql-map-2.dtd和sql-map-config-2.dtd

    引入sql-map-config-2.dtd后,开发者可以确保配置文件的语法正确,避免因格式错误导致的运行时问题。 在实际应用中,这两个DTD文件通常会被引用到对应的XML配置文件顶部,如下所示: ```xml &lt;!DOCTYPE sqlMap ...

    x-pack-sql-jdbc-6.4-7.6各个版本jdbc驱动--百度网盘下载

    x-pack-sql-jdbc-6.4.0到x-pack-sql-jdbc-7.6.0各个版本jdbc驱动下载

    SQL2019-SSEI-Eval SQL Server 2019 正式版安装引导介质

    SQL Server 2019 正式版安装引导介质,可下载ISO到本地进行安装。不支持Windows7及以下系统安装。

    x-pack-sql-jdbc-6.5.4.jar

    x-pack-sql-jdbc-6.5.4.jar

    flume-ng-sql-source-1.5.2.jar

    flume-ng-sql-source-1.5.2.jar从数据库中增量读取数据到hdfs中的jar包

    SQLPrompt-10.14.0.4064.exe 支持SSMS 19.1

    SQLPrompt-10.14.0.4064.exe 支持SSMS 19.1

    SQL解惑 第二版(中文)pdf带目录

    通过阅读《SQL解惑 第二版》,读者不仅能够理解SQL的基本语法,还能学会如何在实际工作中有效利用SQL解决问题。书中的案例分析使学习过程更为直观,对于初学者和有一定经验的数据库管理员来说,都是一份极好的学习...

    flume-ng-sql-source-1.5.1

    flume-ng-sql-source-1.5.1 flume连接数据库 很好用的工具

    sqldeveloper-17.2.0.188.1159-x64.zip

    sqldeveloper-17.2.0.188.1159-x64.zip oracle mysql 数据库,适合Windows系统,可以链接mysql是一款不错的数据库x64

    SQL解惑(第2版)

    针对每个问题的解决方案均遵循SQL-99标准以及后续的相关标准,这不仅保证了解决方案的前沿性和实用性,也反映出作者对SQL语言及其发展趋势的深刻认识。书中所探讨的问题几乎涵盖了SQL语言的各个方面,包括但不限于...

    sql server-练习卷-问题修改.sql

    sql server-练习卷-问题修改.sql

    SQL解惑(中文版)

    根据提供的标题、描述以及部分上下文内容,我们可以推断出这本书《SQL解惑(中文版)》主要聚焦于SQL技能的提升与深化理解。虽然实际的内容并未给出具体示例或章节概述,但根据书名及简介,我们可以围绕SQL的基础...

    SQL解惑_pdf_againstccb_

    《SQL解惑(第2版)》是一本深入探讨SQL编程问题的专业书籍,旨在帮助读者解决在实际工作中遇到的各种SQL难题。SQL,全称为Structured Query Language,是用于管理和处理关系数据库的标准语言。这本书以问题为导向,...

    SQL解惑解惑

    SQL解惑解惑,意味着我们将深入探讨SQL的常见问题、概念以及解决策略。在这个过程中,我们不仅要理解SQL的基本语法,还要掌握如何有效地查询、更新和管理数据。 首先,让我们从SQL的基础开始。SQL分为四大主要部分...

    收获,不止SQL优化--抓住SQL的本质

    资源名称:收获,不止SQL优化--抓住SQL的本质作者简介:梁敬彬,福富研究院副理事长、公司唯一四星级内训师。不仅是公司特级专家也是国内一线知名数据库专家,其个人及团队在数据库优化和培训领域有着丰富的经验、...

    squirrel-sql-3.8.1-standard.jar

    squirrel-sql-3.8.1-standard.jar squirrel-sql-3.8.1-standard.jar

    azkaban-sql-script-2.5.0.tar.gz

    这个压缩包“azkaban-sql-script-2.5.0.tar.gz”包含的是Azkaban 2.5.0版本的SQL脚本,这些脚本可能用于在数据库中设置和配置Azkaban所需的表结构和权限。以下将详细介绍Azkaban的关键概念、功能以及与SQL脚本的关系...

    sql解惑.pdf

    根据提供的文件信息,此文档的标题是“sql解惑.pdf”,描述为“个人收集电子书,仅用学习使用,不可用于商业用途,如有版权问题,请联系删除!”,标签为“计算机 编程”,而部分内容实际上并未提供与SQL相关的有效...

Global site tag (gtag.js) - Google Analytics