• todd.ayers (4/30/2013)


    I am trying to create a random number generator that would populate a number between 8-48 to 9 different lanes with the only criteria being that each lane number cannot be within 5 of any lane within 3 spaces of it. So what I mean is if lane 4 has a number of 30 then lane 1-2-3 and lane 5-6-7 cannot be within 5 of lane 4's number. Hope this makes sense and any help would be sincerely appreciated....

    No problem. Folks here love this sort of question! Here's a solution for openers:

    ;WITH SemiRandomNumbers AS (

    SELECT Lane = 8 + ABS(CHECKSUM(NEWID()))%41

    FROM syscolumns a

    )

    SELECT *

    FROM (SELECT ID = 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4) s

    CROSS APPLY (

    SELECT TOP 1 Lane1 = Lane FROM SemiRandomNumbers --ORDER BY (SELECT NULL)

    ) l1

    CROSS APPLY (

    SELECT TOP 1 Lane2 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l1.Lane1-5 AND l1.Lane1+5)

    ) l2

    CROSS APPLY (

    SELECT TOP 1 Lane3 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l1.Lane1-5 AND l1.Lane1+5)

    AND NOT (r.Lane BETWEEN l2.Lane2-5 AND l2.Lane2+5)

    ) l3

    CROSS APPLY (

    SELECT TOP 1 Lane4 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l1.Lane1-5 AND l1.Lane1+5)

    AND NOT (r.Lane BETWEEN l2.Lane2-5 AND l2.Lane2+5)

    AND NOT (r.Lane BETWEEN l3.Lane3-5 AND l3.Lane3+5)

    ) l4

    CROSS APPLY (

    SELECT TOP 1 Lane5 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l2.Lane2-5 AND l2.Lane2+5)

    AND NOT (r.Lane BETWEEN l3.Lane3-5 AND l3.Lane3+5)

    AND NOT (r.Lane BETWEEN l4.Lane4-5 AND l4.Lane4+5)

    ) l5

    CROSS APPLY (

    SELECT TOP 1 Lane6 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l3.Lane3-5 AND l3.Lane3+5)

    AND NOT (r.Lane BETWEEN l4.Lane4-5 AND l4.Lane4+5)

    AND NOT (r.Lane BETWEEN l5.Lane5-5 AND l5.Lane5+5)

    ) l6

    CROSS APPLY (

    SELECT TOP 1 Lane7 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l4.Lane4-5 AND l4.Lane4+5)

    AND NOT (r.Lane BETWEEN l5.Lane5-5 AND l5.Lane5+5)

    AND NOT (r.Lane BETWEEN l6.Lane6-5 AND l6.Lane6+5)

    ) l7

    CROSS APPLY (

    SELECT TOP 1 Lane8 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l5.Lane5-5 AND l5.Lane5+5)

    AND NOT (r.Lane BETWEEN l6.Lane6-5 AND l6.Lane6+5)

    AND NOT (r.Lane BETWEEN l7.Lane7-5 AND l7.Lane7+5)

    ) l8

    CROSS APPLY (

    SELECT TOP 1 Lane9 = Lane FROM SemiRandomNumbers r

    WHERE NOT (r.Lane BETWEEN l6.Lane6-5 AND l6.Lane6+5)

    AND NOT (r.Lane BETWEEN l7.Lane7-5 AND l7.Lane7+5)

    AND NOT (r.Lane BETWEEN l8.Lane8-5 AND l8.Lane8+5)

    ) l9

    “Write the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    For fast, accurate and documented assistance in answering your questions, please read this article.
    Understanding and using APPLY, (I) and (II) Paul White
    Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden