TSQL排气可用插槽

TSQL排气可用插槽,tsql,common-table-expression,Tsql,Common Table Expression,我有一组用户,他们可以在特定的会议时段注册。我让他们相互映射,需要填补他们可以见面的第一个可用的位置,而无需双重预订 我已经举了一个例子,说明我是如何解决这个问题的,但我仍停留在如何进一步解决这个问题上 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, DATE

我有一组用户,他们可以在特定的会议时段注册。我让他们相互映射,需要填补他们可以见面的第一个可用的位置,而无需双重预订

我已经举了一个例子,说明我是如何解决这个问题的,但我仍停留在如何进一步解决这个问题上

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

下面是我提出的一个迭代过程:

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 p.rn=@i
    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 p.rn=@i;
    set @i+=1;
end;
go

select reg1, reg2, slot from #poss1
go
结果:


下面是我提出的一个迭代过程:

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 p.rn=@i
    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 p.rn=@i;
    set @i+=1;
end;
go

select reg1, reg2, slot from #poss1
go
结果:


如果您在示例中使用更清晰的名称和有效的ID,这将有所帮助。我猜av是可用的表格,列出了注册者的可用插槽?met是会议,您的示例显示了注册者之间的会议请求:1+2、1+3、4+2?预期输出显示插槽1,但它不存在,大概是11?met.slot是否应使用指定的时间段进行更新?您要查找的代码是否应同时执行多个会议的批量计划,而不会重叠任何会议?它应该得到最佳的时间表吗?是否应考虑met.slot中的现有会议?我问这个问题是因为进行批量查询以找到最佳日程安排是一个非常不同的问题,例如,参见vs使用先到先得的方法逐个进行。@gregmac,你在所有问题上都是对的。我用正确的slots更新了这个问题。至于你的第二个评论,我只需要一些简单的东西。这只是每个阶段性会议的第一次机会。我不需要先到先得的服务,也不需要在同一时段内预订两次的服务,如果您在示例中使用更清晰的名称和有效的ID,这会有所帮助。我猜av是可用的表格,列出了注册者的可用插槽?met是会议,您的示例显示了注册者之间的会议请求:1+2、1+3、4+2?预期输出显示插槽1,但它不存在,大概是11?met.slot是否应使用指定的时间段进行更新?您要查找的代码是否应同时执行多个会议的批量计划,而不会重叠任何会议?它应该得到最佳的时间表吗?是否应考虑met.slot中的现有会议?我问这个问题是因为进行批量查询以找到最佳日程安排是一个非常不同的问题,例如,参见vs使用先到先得的方法逐个进行。@gregmac,你在所有问题上都是对的。我用正确的slots更新了这个问题。至于你的第二个评论,我只需要一些简单的东西。这只是每个阶段性会议的第一次机会。我不需要先到先得的服务,也不需要在同一时段内预订两次的服务。