How to generate a range of numbers between two numbers?

后端 未结 30 1872
执念已碎
执念已碎 2020-11-22 10:16

I have two numbers as input from the user, like for example 1000 and 1050.

How do I generate the numbers between these two numbers, using

相关标签:
30条回答
  • 2020-11-22 10:33

    Here is a generic and relatively fast solution that outputs integers from 1 to @n. It works with any positive integer of @n (very large numbers will cause arithmetic overflow) without needing to add or remove table joins. It doesn't require the use of system tables nor do you to change max recursions.

    declare @n int = 10000 
    
    ;with d as (select * from (values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) x (d)),
    n as ( 
        select d x from d where d > 0 and d <= @n
        union all
        select x * 10 + d from n, d where x * 10 + d <= @n
    )
    select x from n 
    

    You can add an order by clause to sort the numbers.

    0 讨论(0)
  • 2020-11-22 10:34
    -- Generate Numeric Range
    -- Source: http://www.sqlservercentral.com/scripts/Miscellaneous/30397/
    
    CREATE TABLE #NumRange(
        n int
    )
    
    DECLARE @MinNum int
    DECLARE @MaxNum int
    DECLARE @I int
    
    SET NOCOUNT ON
    
    SET @I = 0
    WHILE @I <= 9 BEGIN
        INSERT INTO #NumRange VALUES(@I)
        SET @I = @I + 1
    END
    
    
    SET @MinNum = 1
    SET @MaxNum = 1000000
    
    SELECT  num = a.n +
        (b.n * 10) +
        (c.n * 100) +
        (d.n * 1000) +
        (e.n * 10000)
    FROM    #NumRange a
    CROSS JOIN #NumRange b
    CROSS JOIN #NumRange c
    CROSS JOIN #NumRange d
    CROSS JOIN #NumRange e
    WHERE   a.n +
        (b.n * 10) +
        (c.n * 100) +
        (d.n * 1000) +
        (e.n * 10000) BETWEEN @MinNum AND @MaxNum
    ORDER BY a.n +
        (b.n * 10) +
        (c.n * 100) +
        (d.n * 1000) +
        (e.n * 10000) 
    
    DROP TABLE #NumRange
    
    0 讨论(0)
  • 2020-11-22 10:34

    Oracle 12c; Quick but limited:

    select rownum+1000 from all_objects fetch first 50 rows only;
    

    Note: limited to row count of all_objects view;

    0 讨论(0)
  • 2020-11-22 10:35

    I know I'm 4 years too late, but I stumbled upon yet another alternative answer to this problem. The issue for speed isn't just pre-filtering, but also preventing sorting. It's possible to force the join-order to execute in a manner that the Cartesian product actually counts up as a result of the join. Using slartidan's answer as a jump-off point:

        WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
    SELECT ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
    FROM x ones,     x tens,      x hundreds,       x thousands
    ORDER BY 1
    

    If we know the range we want, we can specify it via @Upper and @Lower. By combining the join hint REMOTE along with TOP, we can calculate only the subset of values we want with nothing wasted.

    WITH x AS (SELECT n FROM (VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(n))
    SELECT TOP (1+@Upper-@Lower) @Lower + ones.n + 10*tens.n + 100*hundreds.n + 1000*thousands.n
    FROM x thousands
    INNER REMOTE JOIN x hundreds on 1=1
    INNER REMOTE JOIN x tens on 1=1
    INNER REMOTE JOIN x ones on 1=1
    

    The join hint REMOTE forces the optimizer to compare on the right side of the join first. By specifying each join as REMOTE from most to least significant value, the join itself will count upwards by one correctly. No need to filter with a WHERE, or sort with an ORDER BY.

    If you want to increase the range, you can continue to add additional joins with progressively higher orders of magnitude, so long as they're ordered from most to least significant in the FROM clause.

    Note that this is a query specific to SQL Server 2008 or higher.

    0 讨论(0)
  • 2020-11-22 10:36

    The best speed when run query

    DECLARE @num INT = 1000
    WHILE(@num<1050)
    begin
     INSERT  INTO [dbo].[Codes]
        (   Code
        ) 
        VALUES (@num)
        SET @num = @num + 1
    end
    
    0 讨论(0)
  • 2020-11-22 10:37

    Here are couple quite optimal and compatible solutions:

    USE master;
    
    declare @min as int;    set @min = 1000;
    declare @max as int;    set @max = 1050;    --null returns all
    
    --  Up to 256 - 2 048 rows depending on SQL Server version
    select  isnull(@min,0)+number.number  as  number
    FROM    dbo.spt_values  AS  number
    WHERE   number."type"                   =   'P'     --integers
        and (   @max                            is null     --return all
            or  isnull(@min,0)+number.number    <=  @max    --return up to max
        )
    order by    number
    ;
    
    --  Up to 65 536 - 4 194 303 rows depending on SQL Server version
    select  isnull(@min,0)+value1.number+(value2.number*numberCount.numbers)  as  number
    FROM  dbo.spt_values            AS  value1
      cross join  dbo.spt_values    AS  value2
      cross join (  --get the number of numbers (depends on version)
        select  sum(1)  as  numbers
        from    dbo.spt_values
        where   spt_values."type"   =   'P' --integers
      )                             as  numberCount
    WHERE   value1."type" = 'P'   --integers
        and value2."type" = 'P'   --integers
        and (   @max    is null     --return all
            or  isnull(@min,0)+value1.number+(value2.number*numberCount.numbers)    
                <=  @max            --return up to max
        )
    order by    number
    ;
    
    0 讨论(0)
提交回复
热议问题