我在名为meetings的表中有以下列:meeting_id - int,start_time - time,end_time - time。假设此表仅包含一个日历日的数据,我需要多少最小数量的房间来容纳所有会议。参加会议的人数/人数并不重要。
以下是解决方案:
select * from
(select t.start_time,
t.end_time,
count(*) - 1 overlapping_meetings,
count(*) minimum_rooms_required,
group_concat(distinct concat(y.start_time,' to ',t.end_time)
separator ' // ') meeting_details from
(select 1 meeting_id, '08:00' start_time, '09:15' end_time union all
select 2, '13:20', '15:20' union all
select 3, '10:00', '14:00' union all
select 4, '13:55', '16:25' union all
select 5, '14:00', '17:45' union all
select 6, '14:05', '17:45') t left join
(select 1 meeting_id, '08:00' start_time, '09:15' end_time union all
select 2, '13:20', '15:20' union all
select 3, '10:00', '14:00' union all
select 4, '13:55', '16:25' union all
select 5, '14:00', '17:45' union all
select 6, '14:05', '17:45') y
on t.start_time between y.start_time and y.end_time
group by start_time, end_time) z;
我的问题 - 这个答案有什么问题吗?即使这没有任何问题,有人可以分享更好的答案吗?
答案 0 :(得分:4)
会议可以重叠"。因此,GROUP BY start_time, end_time
无法解决这个问题。
并非每种算法都可以在SQL中完成。或者,至少,它可能非常低效。
我会使用真正的编程语言进行计算,让数据库保持擅长的状态 - 作为数据存储库。
Build a array of 1440 (minutes in a day) entries; initialize to 0.
Foreach meeting:
Foreach minute in the meeting (excluding last minute):
increment element in array.
Find the largest element in the array -- the number of rooms needed.
答案 1 :(得分:3)
我们假设您有一张名为“会议”的表格。像这样 -
然后,您可以使用此查询获得容纳所有会议所需的最少会议室数。
select max(minimum_rooms_required) from (select count(*) minimum_rooms_required from meetings t left join meetings y on t.start_time between y.start_time and y.end_time group by t.id) z;
这看起来更清晰,更简单,工作正常。
答案 2 :(得分:1)
CREATE TABLE [dbo].[Meetings](
[id] [int] NOT NULL,
[Starttime] [time](7) NOT NULL,
[EndTime] [time](7) NOT NULL) ON [PRIMARY] )GO
样本数据集:
INSERT INTO Meetings VALUES (1,'8:00','09:00')
INSERT INTO Meetings VALUES (2,'8:00','10:00')
INSERT INTO Meetings VALUES (3,'10:00','11:00')
INSERT INTO Meetings VALUES (4,'11:00','12:00')
INSERT INTO Meetings VALUES (5,'11:00','13:00')
INSERT INTO Meetings VALUES (6,'13:00','14:00')
INSERT INTO Meetings VALUES (7,'13:00','15:00')
要查找所需的最小房间数,请运行以下查询:
create table #TempMeeting
(
id int,Starttime time,EndTime time,MeetingRoomNo int,Rownumber int
)
insert into #TempMeeting select id, Starttime,EndTime,0 as MeetingRoomNo,ROW_NUMBER()
over (order by starttime asc) as Rownumber from Meetings
declare @RowCounter int
select top 1 @RowCounter=Rownumber from #TempMeeting order by Rownumber
WHILE @RowCounter<=(Select count(*) from #TempMeeting)
BEGIN
update #TempMeeting set MeetingRoomNo=1
where Rownumber=(select top 1 Rownumber from #TempMeeting where
Rownumber>@RowCounter and Starttime>=(select top 1 EndTime from #TempMeeting
where Rownumber=@RowCounter)and MeetingRoomNo=0)set @RowCounter=@RowCounter+1
END
select count(*) from #TempMeeting where MeetingRoomNo=0
答案 3 :(得分:0)
请考虑具有列meetings
和id, start_time
的表end_time
。然后,以下查询应给出正确答案。
with mod_meetings as (select id, to_timestamp(start_time, 'HH24:MI')::TIME as start_time,
to_timestamp(end_time, 'HH24:MI')::TIME as end_time from meetings)
select CASE when max(a_cnt)>1 then max(a_cnt)+1
when max(a_cnt)=1 and max(b_cnt)=1 then 2 else 1 end as rooms
from
(select count(*) as a_cnt, a.id, count(b.id) as b_cnt from mod_meetings a left join mod_meetings b
on a.start_time>b.start_time and a.start_time<b.end_time group by a.id) join_table;
答案 4 :(得分:0)
样本数据:
DROP TABLE IF EXISTS meeting;
CREATE TABLE "meeting" (
"meeting_id" INTEGER NOT NULL UNIQUE,
"start_time" TEXT NOT NULL,
"end_time" TEXT NOT NULL,
PRIMARY KEY("meeting_id")
);
INSERT INTO meeting values (1,'08:00','14:00');
INSERT INTO meeting values (2,'09:00','10:30');
INSERT INTO meeting values (3,'11:00','12:00');
INSERT INTO meeting values (4,'12:00','13:00');
INSERT INTO meeting values (5,'10:15','11:00');
INSERT INTO meeting values (6,'12:00','13:00');
INSERT INTO meeting values (7,'10:00','10:30');
INSERT INTO meeting values (8,'11:00','13:00');
INSERT INTO meeting values (9,'11:00','14:00');
INSERT INTO meeting values (10,'12:00','14:00');
INSERT INTO meeting values (11,'10:00','14:00');
INSERT INTO meeting values (12,'12:00','14:00');
INSERT INTO meeting values (13,'10:00','14:00');
INSERT INTO meeting values (14,'13:00','14:00');
解决方案:
DROP VIEW IF EXISTS Final;
CREATE VIEW Final AS SELECT time, group_concat(event), sum(num) num from (
select start_time time, 's' event, 1 num from meeting
union all
select end_time time, 'e' event, -1 num from meeting)
group by 1
order by 1;
select max(room) AS Min_Rooms_Required FROM (
select
a.time,
sum(b.num) as room
from
Final a
, Final b
where a.time >= b.time
group by a.time
order by a.time
);
答案 5 :(得分:0)
以下是gashu正常工作的代码的说明(或者其他非代码说明,说明如何使用任何语言解决该问题)。 首先,如果将变量“ minimum_rooms_required”重命名为“ overlap”,则整个内容将更易于理解。因为对于每个开始时间或结束时间,我们都想知道进行中的重叠会议的数量。当我们找到最大值时,这意味着没有比重叠的数量少的东西了,因为它们重叠了。
顺便说一句,我认为代码可能有错误。它应该检查y.start_time和y.end_time之间的t.start_time或t.end_time。反例:会议1开始于8:00,结束于11:00,会议2开始于10:00,结束于12:00。 (我把它作为对加舒的回答的评论,但我没有足够的声誉)
答案 6 :(得分:0)
我会选择 Lead() 分析函数
select
sum(needs_room_ind) as min_rooms
from (
select
id,
start_time,
end_time,
case when lead(start_time,1) over (order by start_time asc) between start_time
and end_time then 1 else 0 end as needs_room_ind
from
meetings
) a