2011-12-12 47 views
2

我有一组用户在注册特定会议(插槽)时可以使用它们。我把它们映射到对方,并且需要填写他们可以同时遇到的第一个可用插槽,而无需对它们进行双重预订。TSQL排空可用插槽

我已经包含了一个如何到达解决问题的例子,但我一直在坚持如何进一步。

CREATE TABLE #Slot (slot int, start datetime) 
INSERT INTO #Slot VALUES (11, DATEADD(hour, 1, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (22, DATEADD(hour, 2, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (31, DATEADD(hour, 3, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (44, DATEADD(hour, 4, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (56, DATEADD(hour, 5, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (61, DATEADD(hour, 6, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (77, DATEADD(hour, 7, '1/1/1900 7:00:00')) 
INSERT INTO #Slot VALUES (83, DATEADD(hour, 8, '1/1/1900 7:00:00')) 

CREATE TABLE #Av (reg int, slot int) 
INSERT INTO #Av 
SELECT 1, slot 
FROM #Slot 
INSERT INTO #Av 
SELECT 2, slot 
FROM #Slot 
INSERT INTO #Av 
SELECT 3, slot 
FROM #Slot 
INSERT INTO #Av 
SELECT 4, slot 
FROM #Slot 


CREATE TABLE #Met (reg1 int, reg2 int, slot int) 
INSERT INTO #Met (reg1, reg2) VALUES (1, 2) 
INSERT INTO #Met (reg1, reg2) VALUES (1, 3) 
INSERT INTO #Met (reg1, reg2) VALUES (4, 2) 

什么我最终使用以下CTE是他们可以见面的所有时间,但我不知道如何最终只有三行。我期待着与(使用所提供的数据),以结束这样的:

reg1 reg2 slot 
1  2  11 
1  3  22 --since 1 is meeting with 2 already in slot 11 
4  2  22 --since 2 is meeting with 1 already in slot 11 

这里是我迄今为止...基本上所有选项,但不能踏踏实实地三行:

with poss(opt, r1, r2, slot) AS 
(
SELECT 
    ROW_NUMBER() OVER(PARTITION BY m.reg1, m.reg2 ORDER BY s1.start), 
    m.reg1, m.reg2, s1.slot 
FROM #Met m 
INNER JOIN #Av r1 ON m.reg1 = r1.reg 
INNER JOIN #Slot s1 ON r1.slot = s1.slot 
INNER JOIN #Av r2 ON m.reg2 = r2.reg 
INNER JOIN #Slot s2 ON r2.slot = s2.slot 
WHERE r1.slot = r2.slot 
) 

SELECT 
    * 
FROM poss e 
INNER JOIN #met m ON e.r1 = m.reg1 AND e.r2 = m.reg2 
ORDER BY opt 
+0

如果您在示例中使用了更清晰的名称和有效的ID,它将有所帮助。我猜#av是可用表格,列出了注册人对插槽的可用性? #met是会议,并且您的示例显示了注册人之间的会议请求:1 + 2,1 + 3,4 + 2?预期的输出显示插槽1,但不存在,大概你的意思是11?应该使用分配的插槽更新#met.slot? – gregmac

+0

您正在寻找的代码是否应该一次执行多个会议的批量调度,而不会重叠任何会议?它应该得到最佳的时间表吗?是否应该考虑#met.slot中的现有会议?我问这个问题是因为这是一个*非常*不同的问题来做一个批量查询来找到一个最佳的时间表(例如,参见http://stackoverflow.com/questions/2746309/best-fit-scheduling-algorithm)vs做一次性采用先到先得的方法。 – gregmac

+0

@gregmac,你对所有问题都是正确的。我用正确的插槽更新了问题 – Benny

回答

0

这是一个反复的过程,我想出了:

with poss(opt, r1, r2, slot) AS 
(
    SELECT 
     ROW_NUMBER() OVER(PARTITION BY m.reg1, m.reg2 ORDER BY s1.start), 
     m.reg1, m.reg2, s1.slot 
    FROM #Met m 
    INNER JOIN #Av r1 ON m.reg1 = r1.reg 
    INNER JOIN #Slot s1 ON r1.slot = s1.slot 
    INNER JOIN #Av r2 ON m.reg2 = r2.reg 
    INNER JOIN #Slot s2 ON r2.slot = s2.slot 
    WHERE r1.slot = r2.slot 
) 
, cs as (
    SELECT 
     reg1, reg2, e.slot 
     , cr=checksum(reg1,reg2) 
     , cs1=checksum(reg1,e.slot) 
     , cs2=checksum(reg2,e.slot) 
     , rn=row_number()over(order by e.slot,reg1,reg2) 
    FROM poss e 
    INNER JOIN #met m ON e.r1 = m.reg1 AND e.r2 = m.reg2 
) 
select * 
into #poss 
from cs 
order by rn 
go 

select top 0 * into #poss1 --this will hold the final results 
from #poss 

declare @i int=1; 

while @i <= (select count(*) from #Met) begin 
    insert into #poss1 
    select * from #poss p 
    where not exists(select 1 from #poss (nolock) where (cr=p.cr or cs1=p.cs1 or cs2=p.cs2) and rn<p.rn) 
    and [email protected] 
    order by slot, reg1, reg2 
    set @i+=1; 
end; 

while @i <= (select count(*) from #poss) begin 
    insert into #poss1 
    select * from #poss p 
    where not exists(select 1 from #poss1 (nolock) where (cr=p.cr or cs1=p.cs1 or cs2=p.cs2)) 
    and [email protected]; 
    set @i+=1; 
end; 
go 

select reg1, reg2, slot from #poss1 
go 

结果:

enter image description here