What is the best way to create and populate a numbers table?

后端 未结 11 2516
悲&欢浪女
悲&欢浪女 2020-11-21 13:28

I\'ve seen many different ways to create and populate a numbers table. However, what is the best way to create and populate one? With \"best\" being defined from most to l

11条回答
  •  悲哀的现实
    2020-11-21 13:57

    Here is a couple of extra methods:
    Method 1

    IF OBJECT_ID('dbo.Numbers', 'U') IS NOT NULL
        DROP TABLE dbo.Numbers
    GO
    
    CREATE TABLE Numbers (Number int NOT NULL PRIMARY KEY);
    GO
    
    DECLARE @i int = 1;
    INSERT INTO dbo.Numbers (Number) 
    VALUES (1),(2);
    
    WHILE 2*@i < 1048576
    BEGIN
        INSERT INTO dbo.Numbers (Number) 
        SELECT Number + 2*@i
        FROM dbo.Numbers;
        SET @i = @@ROWCOUNT;
    END
    GO
    
    SELECT COUNT(*) FROM Numbers AS RowCownt --1048576 rows
    

    Method 2

    IF OBJECT_ID('dbo.Numbers', 'U') IS NOT NULL
        DROP TABLE dbo.Numbers
    GO
    
    CREATE TABLE dbo.Numbers (Number int NOT NULL PRIMARY KEY);
    GO
    
    DECLARE @i INT = 0; 
    INSERT INTO dbo.Numbers (Number) 
    VALUES (1);
    
    WHILE @i <= 9
    BEGIN
        INSERT INTO dbo.Numbers (Number)
        SELECT N.Number + POWER(4, @i) * D.Digit 
        FROM dbo.Numbers AS N
            CROSS JOIN (VALUES(1),(2),(3)) AS D(Digit)
        ORDER BY D.Digit, N.Number
        SET @i = @i + 1;
    END
    GO
    
    SELECT COUNT(*) FROM dbo.Numbers AS RowCownt --1048576 rows
    

    Method 3

    IF OBJECT_ID('dbo.Numbers', 'U') IS NOT NULL
        DROP TABLE dbo.Numbers
    GO
    
    CREATE TABLE Numbers (Number int identity NOT NULL PRIMARY KEY, T bit NULL);
    
    WITH
        T1(T) AS (SELECT T FROM (VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10)) AS T(T)) --10 rows
       ,T2(T) AS (SELECT A.T FROM T1 AS A CROSS JOIN T1 AS B CROSS JOIN T1 AS C) --1,000 rows
       ,T3(T) AS (SELECT A.T FROM T2 AS A CROSS JOIN T2 AS B CROSS JOIN T2 AS C) --1,000,000,000 rows
    
    INSERT INTO dbo.Numbers(T)
    SELECT TOP (1048576) NULL
    FROM T3;
    
    ALTER TABLE Numbers
        DROP COLUMN T; 
    GO
    
    SELECT COUNT(*) FROM dbo.Numbers AS RowCownt --1048576 rows
    

    Method 4, taken from Defensive Database Programming book by Alex Kuznetsov

    IF OBJECT_ID('dbo.Numbers', 'U') IS NOT NULL
        DROP TABLE dbo.Numbers
    GO
    
    CREATE TABLE Numbers (Number int NOT NULL PRIMARY KEY);
    GO
    
    DECLARE @i INT = 1 ; 
    INSERT INTO dbo.Numbers (Number) 
    VALUES (1);
    
    WHILE @i < 524289 --1048576
    BEGIN; 
        INSERT INTO dbo.Numbers (Number) 
        SELECT Number + @i 
        FROM dbo.Numbers; 
        SET @i = @i * 2 ; 
    END
    GO
    
    SELECT COUNT(*) FROM dbo.Numbers AS RowCownt --1048576 rows
    

    Method 5, taken from Arrays and Lists in SQL Server 2005 and Beyond article by Erland Sommarskog

    IF OBJECT_ID('dbo.Numbers', 'U') IS NOT NULL
        DROP TABLE dbo.Numbers
    GO
    
    CREATE TABLE Numbers (Number int NOT NULL PRIMARY KEY);
    GO
    
    WITH digits (d) AS (
       SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL
       SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL
       SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL
       SELECT 0)
    INSERT INTO Numbers (Number)
       SELECT Number
       FROM   (SELECT i.d + ii.d * 10 + iii.d * 100 + iv.d * 1000 +
                      v.d * 10000 + vi.d * 100000 AS Number
               FROM   digits i
               CROSS  JOIN digits ii
               CROSS  JOIN digits iii
               CROSS  JOIN digits iv
               CROSS  JOIN digits v
               CROSS  JOIN digits vi) AS Numbers
       WHERE  Number > 0
    GO
    
    SELECT COUNT(*) FROM dbo.Numbers AS RowCownt --999999 rows
    

    Summary:
    Among those 5 methods, method 3 seems to be the fastest.

提交回复
热议问题