如何有效地生成更大的彩票号码集

TSQ*_*oob 0 t-sql

我是 SQL 的初学者,我一直在寻找更多的 SQL 经验,因此我决定设计一个过程来生成 X 数量的随机乐透选择。我所在地区的彩票允许您从 1-47 中选择 5 个号码,以及从 1-27 中选择 1 个“超级”号码。诀窍是“mega”数字可以与之前的 5 个数字重复,即 1、2、3、4、5、mega 1。

我创建了以下过程来生成 1000 万个彩票选秀权,该过程花了 12 小时 57 分钟才能完成。而我的朋友用 java 测试了同样的事情,只花了几秒钟。我想知道我是否可以对代码进行任何改进,或者我是否犯了任何错误?我对此很陌生,因此我正在努力学习更好的方法等,欢迎所有评论。

USE lotto
DECLARE 
@counter INT,
@counter1 INT,
@pm SMALLINT,
@i1 SMALLINT,
@i2 SMALLINT,
@i3 SMALLINT,
@i4 SMALLINT,
@i5 SMALLINT,
@sort int

SET @counter1=0

TRUNCATE TABLE picks 

WHILE @counter1<10000000
BEGIN
    TRUNCATE TABLE sort
    SET @counter = 1
        WHILE @counter < 6
        BEGIN
            INSERT INTO sort (pick)
            SELECT CAST(((47+ 1) - 0)   * RAND() + 1 AS TINYINT)
            IF (SELECT count(distinct pick) FROM sort)<@counter 
                BEGIN
                TRUNCATE TABLE sort
                SET @counter=1
                END
            ELSE IF (SELECT COUNT(DISTINCT pick) FROM sort)=@counter 
                BEGIN
                SET @counter = @counter + 1
            END
        END



    SET @sort = 0
        WHILE @sort<5
        BEGIN
            UPDATE sort
            SET sort=@sort
            WHERE pick = (SELECT min(pick) FROM sort WHERE sort is null)
            SET @sort=@sort + 1
        END

    SET @i1 = (SELECT pick FROM sort WHERE sort = 0)
    SET @i2 = (SELECT pick FROM sort WHERE sort = 1)
    SET @i3 = (SELECT pick FROM sort WHERE sort = 2)
    SET @i4 = (SELECT pick FROM sort WHERE sort = 3)
    SET @i5 = (SELECT pick FROM sort WHERE sort = 4)
    SET @pm = (CAST(((27+ 1) - 0)   * RAND() + 1 AS TINYINT))

    INSERT INTO picks(
        First,
        Second,
        Third,
        Fourth,
        Fifth,
        Mega,
        Sequence
        )
    Values(
        @i1,
        @i2,
        @i3,
        @i4,
        @i5,
        @pm,
        @counter1
        )
    SET @counter1 = @counter1+1
END
Run Code Online (Sandbox Code Playgroud)

Ari*_*ion 5

我在 0 秒内生成了 10000 行。我用另一种方式做到了。希望对你有帮助

;WITH Nbrs ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 10000 )
SELECT 
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS First,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Second,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Third,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Fourth,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Fifth,
    (ABS(CHECKSUM(NewId())) % 27 + 1) AS Mega,
    Nbrs.n AS Sequence 
FROM 
    Nbrs
OPTION ( MAXRECURSION 0 )
Run Code Online (Sandbox Code Playgroud)

10000 行 0 秒
100000 行 1 秒
1000000 行 13 秒
10000000 行 02 分 21 秒

或者使用交叉连接

WITH E00(N) AS (SELECT 1 UNION ALL SELECT 1),
        E02(N) AS (SELECT 1 FROM E00 a, E00 b),
        E04(N) AS (SELECT 1 FROM E02 a, E02 b),
        E08(N) AS (SELECT 1 FROM E04 a, E04 b),
        E16(N) AS (SELECT 1 FROM E08 a, E08 b),
        E32(N) AS (SELECT 1 FROM E16 a, E16 b),
   Nbrs(N) AS (SELECT ROW_NUMBER() OVER (ORDER BY N) FROM E32)
 SELECT 
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS First,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Second,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Third,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Fourth,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Fifth,
    (ABS(CHECKSUM(NewId())) % 27 + 1) AS Mega,
    Nbrs.n AS Sequence 
   FROM Nbrs
  WHERE N <= 10000000;
Run Code Online (Sandbox Code Playgroud)

10000 行 0 秒
100000 行 1 秒
1000000 行 14 秒
10000000 行 03 分 29 秒

我还应该提到我使用的原因

(ABS(CHECKSUM(NewId())) % 47 + 1)
Run Code Online (Sandbox Code Playgroud)

是它每行返回一个随机数。解决方案与

CAST(((47+ 1) - 0)   * RAND() + 1 AS TINYINT)
Run Code Online (Sandbox Code Playgroud)

如果一次性选择它们,则为每一行返回相同的随机数。要测试此运行此示例:

    ;WITH Nbrs ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 5 )
SELECT
    CAST(((47+ 1) - 0)   * RAND() + 1 AS TINYINT) AS Random,
    (ABS(CHECKSUM(NewId())) % 47 + 1) AS RadomCheckSum,
    Nbrs.n AS Sequence
FROM Nbrs
Run Code Online (Sandbox Code Playgroud)

好的。所以我确实看到了你的评论,我也有一个解决方案。如果你真的想订购数字。算法的复杂度增加,这也意味着算法的时间增加。但我仍然认为这是可行的。但不是以同样简洁的方式。

--Yeah declaring a temp table for just the random order number
DECLARE @tbl TABLE(value int)

--The same function but with the number of the random numbers
;WITH Nbrs ( n ) AS (
        SELECT 1 UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 5 )
INSERT INTO @tbl
(
    value
)
SELECT
    Nbrs.n AS Sequence
FROM Nbrs 

;WITH Nbrs ( n ) AS (
        SELECT CAST(1 as BIGINT) UNION ALL
        SELECT 1 + n FROM Nbrs WHERE n < 100000 )
SELECT
    tblOrderRandomNumbers.[1] AS First,
    tblOrderRandomNumbers.[2] AS Second,
    tblOrderRandomNumbers.[3] AS Third,
    tblOrderRandomNumbers.[4] AS Fourth,
    tblOrderRandomNumbers.[5] AS Fifth,
    (ABS(CHECKSUM(NewId())) % 27 + 1) AS Mega,
    Nbrs.n AS Sequence
FROM
    Nbrs
    --This cross join. Joins with the declared table
    CROSS JOIN
        (
            SELECT
                [1], [2], [3], [4], [5]
            FROM
            (
            SELECT
                Random,
                ROW_NUMBER() OVER(ORDER BY tblRandom.Random ASC) AS RowNumber
            FROM
                (
                SELECT
                    (ABS(CHECKSUM(NewId())) % 47 + 1) AS Random
                FROM
                    @tbl AS tblNumbers
                ) AS tblRandom

            )AS tblSortedRadom
            --A pivot makes the rows to columns. Using the row index over order of the random number
            PIVOT
            (
                AVG(Random)
            FOR RowNumber IN ([1], [2], [3], [4],[5])
            ) as pivottable
        ) AS tblOrderRandomNumbers
OPTION ( MAXRECURSION 0 )
Run Code Online (Sandbox Code Playgroud)

但我仍然设法在短时间内完成
10000 行:0 秒
100000 行:4 秒
1000000 行:43 秒
10000000 行:7 分 9 秒

我希望这有帮助