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

时间:2009-06-23 11:53:06

标签: 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:如果某人在第1天测试了他的网站,那么轮到他们应该在第4天而不是在第4天之前 - 仅适用于当前周。因此,如果A和D在22日测试一个站点,B和E在23日测试它,在24日测试C和F测试,那么在本周,A和D只能在25日测试该站点。星期天是假期

规则2:每周,这一对都应该改变。规则1仍适用于新配对。

规则3:属于特定网站的人无法测试其他网站。

  

在查询中,我应该可以   后来改变了两人的对   并使他们一次3人或   将每个站点的人数从6增加到10,用   对代码进行了一些更改。

示例数据

DECLARE @Site TABLE
(
SiteID int,
SiteNm varchar(10)
)

DECLARE @Person TABLE
(
PersonID int,
PersonName char(1),
SiteID int
)

INSERT @Site
SELECT 1, 'Site1' UNION ALL
SELECT 2, 'Site2' UNION ALL
SELECT 3, 'Site3' UNION ALL
SELECT 4, 'Site4' 

INSERT @Person
SELECT 1, 'A', 1 UNION ALL
SELECT 2, 'B', 1 UNION ALL
SELECT 3, 'C', 1 UNION ALL
SELECT 4, 'D', 1 UNION ALL
SELECT 5, 'E', 1 UNION ALL
SELECT 6, 'F', 1 UNION ALL
SELECT 7, 'G', 2 UNION ALL
SELECT 8, 'H', 2 UNION ALL
SELECT 9, 'I', 2 UNION ALL
SELECT 10, 'J', 2 UNION ALL
SELECT 11, 'K', 2 UNION ALL
SELECT 12, 'L', 2 UNION ALL
SELECT 13, 'M', 3 UNION ALL
SELECT 14, 'N', 3 UNION ALL
SELECT 15, 'O', 3 UNION ALL
SELECT 16, 'P', 3 UNION ALL
SELECT 17, 'Q', 3 UNION ALL
SELECT 18, 'R', 3 UNION ALL
SELECT 19, 'S', 4 UNION ALL
SELECT 20, 'T', 4 UNION ALL
SELECT 21, 'U', 4 UNION ALL
SELECT 22, 'V', 4 UNION ALL
SELECT 23, 'W', 4 UNION ALL
SELECT 24, 'X', 4

以下是我想要输出的方式:

Date    Site 1    Site 2     Site 3     Site 4
22Jun    A,D        H,I       N,R        T,W
23Jun    B,E        J,K       M,P        V,X
...
26Jun    A,D         H,I       N,R        T,W  
...
29Jun    F,A         K,L       R,Q        W,U

等等

你能帮我查询一下吗?

  

在查询中,我应该可以   后来改变了两人的对   并使他们一次3人或   将每个站点的人数从6增加到10,用   对代码的更改很少。我想要这种灵活性

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

这不是SQL要处理的内容。我绝对会将这种算法逻辑转移到代码中。

如果由于某种原因,您无法将其移动到代码中并且必须从数据库中获取预测信息,那么如果您使用的是MS SQL Server 2005或2008,我会考虑使用SqlSever中的CLR程序集。 / p>

Reference from MSDN on how to use CLR in SQL

答案 2 :(得分:0)

技术上可以通过嵌套循环和嵌入式查询在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中的一切都非常难看。使用更通用的语言更容易做到这一点。