Sql 预测下一个记录的棘手问题

Sql 预测下一个记录的棘手问题,sql,sql-server,Sql,Sql Server,我正在做一个测试场景 每个站点6人 Site 1 - A, B, C, D, E, F Site 2 - G, H, I, J, K, L Site 3 - M, N, O, P, Q, R Site 4 - S, T, U, V, W, X 我想写一个查询,可以建议我的日期谁可以测试网站的人-一次两个。规则如下: 规则1:如果一个人在第一天测试了他的网站,那么他的轮到应该在第四天,而不是在那之前-只适用于本周。因此,如果A和D在22日测试A站点,B和E在23日测试,C和F在24日测试,那么本

我正在做一个测试场景

每个站点6人

Site 1 - A, B, C, D, E, F
Site 2 - G, H, I, J, K, L
Site 3 - M, N, O, P, Q, R
Site 4 - S, T, U, V, W, X
我想写一个查询,可以建议我的日期谁可以测试网站的人-一次两个。规则如下:

规则1:如果一个人在第一天测试了他的网站,那么他的轮到应该在第四天,而不是在那之前-只适用于本周。因此,如果A和D在22日测试A站点,B和E在23日测试,C和F在24日测试,那么本周,A和D只能在25日测试站点。星期天是假日

规则2:每星期,这对情侣都应该换衣服。规则1仍然适用于新的一对

规则3:属于特定站点的人员不能测试其他站点

在查询中,我应该能够 后来换了两个人的一对 让他们一次三个人,或者 将每个站点上的人数从6人增加到10人 对代码的更改很少

样本数据

以下是我希望输出的方式:

等等

你能帮我查询一下吗

在查询中,我应该能够 后来换了两个人的一对 让他们一次三个人,或者 将每个站点上的人数从6人增加到10人 对代码的更改很少。我想要这种灵活性


这不是SQL要处理的事情。我肯定会把这种算法逻辑转换成代码

如果由于某种原因,你不能将它移动到代码中,并且绝对需要从数据库中获取预测信息,那么如果你使用MS SQL Server 2005或2008,我会在SQLServer中考虑CLR程序集。


通过嵌套循环和嵌入式查询,在T-SQL中实现这一点在技术上是可能的

--loop over sites
    --loop over n-day periods (initially n=3, so day1->day4, discounting sundays)
        -- loop over pairs in that period
            --match people who are n+x IDs apart, x increments each n-day loop,
               --need to mod this against count(persons per site)
        -- end pairs loop
    -- end n-day loop
-- end sites loop

在T-SQL中都非常丑陋。用一种更通用的语言做这件事要容易得多。

这在代码中会容易得多。。。我不明白你的意思是什么?你是说林克?你能告诉我怎么做吗。谢谢你。您将需要以下一个或多个:带有非平凡连接谓词的自连接、递归CTE、c排序函数、d datepart和dateadd函数。老实说,听起来像是一个家庭作业,有着武断的规则。
WITH    sets AS
        (
        SELECT  SiteID, SUBSTRING(CAST(PersonID AS VARCHAR(MAX)) + SPACE(8), 1, 8)AS result, 1 AS rn
        FROM    @Person p
        UNION ALL
        SELECT  p2.SiteID, s.result + SUBSTRING(CAST(PersonID AS VARCHAR(MAX)) + SPACE(8), 1, 8), rn + 1
        FROM    sets s
        JOIN    @Person p2
        ON      p2.siteid = s.siteid
                AND PATINDEX('%' + SUBSTRING(CAST(PersonID AS VARCHAR(MAX)) + SPACE(8), 1, 8) + '%', s.result) = 0
        ),
        cal AS
        (
        SELECT  1 AS rn
        UNION ALL
        SELECT  rn + 1
        FROM    cal
        WHERE   rn < 99
        ),
        pairs AS
        (
        SELECT  SiteId, result, ROW_NUMBER() OVER (PARTITION BY siteid ORDER BY rn2 % 30) pn
        FROM    (
                SELECT  s.*,
                        ROW_NUMBER() OVER (PARTITION BY siteid ORDER BY siteid) AS rn2
                FROM    sets s
                WHERE   rn = 6
                ) q
        WHERE   rn2 % 2 > 0
                AND rn2 % 12 > 5
                AND rn2 % 240 > 119
        )
SELECT  CAST('2009-01-01' AS DATETIME) + rn, siteid,
        SUBSTRING(result, 1 + (rn % 3) * 16, 8) AS first,
        SUBSTRING(result, 1 + (rn % 3) * 16 + 8, 8) AS second
FROM    cal
JOIN    pairs
ON      pn = (rn / 7 + 1)
        AND DATEPART(weekday, CAST('2009-01-01' AS DATETIME) + rn) <> 1
--loop over sites
    --loop over n-day periods (initially n=3, so day1->day4, discounting sundays)
        -- loop over pairs in that period
            --match people who are n+x IDs apart, x increments each n-day loop,
               --need to mod this against count(persons per site)
        -- end pairs loop
    -- end n-day loop
-- end sites loop
WITH    sets AS
        (
        SELECT  SiteID, SUBSTRING(CAST(PersonID AS VARCHAR(MAX)) + SPACE(8), 1, 8)AS result, 1 AS rn
        FROM    @Person p
        UNION ALL
        SELECT  p2.SiteID, s.result + SUBSTRING(CAST(PersonID AS VARCHAR(MAX)) + SPACE(8), 1, 8), rn + 1
        FROM    sets s
        JOIN    @Person p2
        ON      p2.siteid = s.siteid
                AND PATINDEX('%' + SUBSTRING(CAST(PersonID AS VARCHAR(MAX)) + SPACE(8), 1, 8) + '%', s.result) = 0
        ),
        cal AS
        (
        SELECT  1 AS rn
        UNION ALL
        SELECT  rn + 1
        FROM    cal
        WHERE   rn < 99
        ),
        pairs AS
        (
        SELECT  SiteId, result, ROW_NUMBER() OVER (PARTITION BY siteid ORDER BY rn2 % 30) pn
        FROM    (
                SELECT  s.*,
                        ROW_NUMBER() OVER (PARTITION BY siteid ORDER BY siteid) AS rn2
                FROM    sets s
                WHERE   rn = 6
                ) q
        WHERE   rn2 % 2 > 0
                AND rn2 % 12 > 5
                AND rn2 % 240 > 119
        )
SELECT  CAST('2009-01-01' AS DATETIME) + rn, siteid,
        SUBSTRING(result, 1 + (rn % 3) * 16, 8) AS first,
        SUBSTRING(result, 1 + (rn % 3) * 16 + 8, 8) AS second
FROM    cal
JOIN    pairs
ON      pn = (rn / 7 + 1)
        AND DATEPART(weekday, CAST('2009-01-01' AS DATETIME) + rn) <> 1