Generate an integer sequence in MySQL

前端 未结 16 2695
南旧
南旧 2020-11-22 06:47

I need to do a join with a table/result-set/whatever that has the integers n to m inclusive. Is there a trivial way to get that without just buildi

相关标签:
16条回答
  • 2020-11-22 07:07

    If you happen to be using the MariaDB fork of MySQL, the SEQUENCE engine allows direct generation of number sequences. It does this by using virtual (fake) one column tables.

    For example, to generate the sequence of integers from 1 to 1000, do this

         SELECT seq FROM seq_1_to_1000;
    

    For 0 to 11, do this.

         SELECT seq FROM seq_0_to_11;
    

    For a week's worth of consecutive DATE values starting today, do this.

    SELECT FROM_DAYS(seq + TO_DAYS(CURDATE)) dateseq FROM seq_0_to_6
    

    For a decade's worth of consecutive DATE values starting with '2010-01-01' do this.

    SELECT FROM_DAYS(seq + TO_DAYS('2010-01-01')) dateseq
      FROM seq_0_to_3800
     WHERE FROM_DAYS(seq + TO_DAYS('2010-01-01')) < '2010-01-01' + INTERVAL 10 YEAR
    

    If you don't happen to be using MariaDB, please consider it.

    0 讨论(0)
  • 2020-11-22 07:07

    try this.. it works for me in mysql version 8.0. you can modify below query according to your required range

    WITH recursive numbers AS (
        select 0 as Date
       union all
       select Date + 1
       from numbers
       where Date < 10)
    select * from numbers;
    

    and yes without creating a table as mentioned in your post

    0 讨论(0)
  • 2020-11-22 07:08

    Sequence of numbers between 1 and 100.000:

    SELECT e*10000+d*1000+c*100+b*10+a n FROM
    (select 0 a union all 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) t1,
    (select 0 b union all 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) t2,
    (select 0 c union all 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) t3,
    (select 0 d union all 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) t4,
    (select 0 e union all 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) t5
    order by 1
    

    I use it to audit if some number is out of sequence, something like this:

    select * from (
        select 121 id
        union all select 123
        union all select 125
        union all select 126
        union all select 127
        union all select 128
        union all select 129
    ) a
    right join (
        SELECT e*10000+d*1000+c*100+b*10+a n FROM
        (select 0 a union all 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) t1,
        (select 0 b union all 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) t2,
        (select 0 c union all 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) t3,
        (select 0 d union all 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) t4,
        (select 0 e union all 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) t5
        order by 1
    ) seq on seq.n=a.id
    where seq.n between 121 and 129
    and   id is null
    

    The result will be the gap of number 122 and 124 of sequence between 121 and 129:

    id     n
    ----   ---
    null   122
    null   124
    

    Maybe it helps someone!

    0 讨论(0)
  • 2020-11-22 07:08

    You appear to be able to construct reasonably large sets with:

    select 9 union all select 10 union all select 11 union all select 12 union all select 13 ...
    

    I got a parser stack overflow in the 5300's, on 5.0.51a.

    0 讨论(0)
  • 2020-11-22 07:13

    Warning: if you insert numbers one row at a time, you'll end up executing N commands where N is the number of rows you need to insert.

    You can get this down to O(log N) by using a temporary table (see below for inserting numbers from 10000 to 10699):

    mysql> CREATE TABLE `tmp_keys` (`k` INTEGER UNSIGNED, PRIMARY KEY (`k`));
    Query OK, 0 rows affected (0.11 sec)
    
    mysql> INSERT INTO `tmp_keys` VALUES (0),(1),(2),(3),(4),(5),(6),(7);
    Query OK, 8 rows affected (0.03 sec)
    Records: 8  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+8 from `tmp_keys`;
    Query OK, 8 rows affected (0.02 sec)
    Records: 8  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+16 from `tmp_keys`;
    Query OK, 16 rows affected (0.03 sec)
    Records: 16  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+32 from `tmp_keys`;
    Query OK, 32 rows affected (0.03 sec)
    Records: 32  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+64 from `tmp_keys`;
    Query OK, 64 rows affected (0.03 sec)
    Records: 64  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+128 from `tmp_keys`;
    Query OK, 128 rows affected (0.05 sec)
    Records: 128  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+256 from `tmp_keys`;
    Query OK, 256 rows affected (0.03 sec)
    Records: 256  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO `tmp_keys` SELECT k+512 from `tmp_keys`;
    Query OK, 512 rows affected (0.11 sec)
    Records: 512  Duplicates: 0  Warnings: 0
    
    mysql> INSERT INTO inttable SELECT k+10000 FROM `tmp_keys` WHERE k<700;
    Query OK, 700 rows affected (0.16 sec)
    Records: 700  Duplicates: 0  Warnings: 0
    

    edit: fyi, unfortunately this won't work with a true temporary table with MySQL 5.0 as it can't insert into itself (you could bounce back and forth between two temporary tables).

    edit: You could use a MEMORY storage engine to prevent this from actually being a drain on the "real" database. I wonder if someone has developed a "NUMBERS" virtual storage engine to instantiate virtual storage to create sequences such as this. (alas, nonportable outside MySQL)

    0 讨论(0)
  • 2020-11-22 07:21

    This query generates numbers from 0 to 1023. I believe it would work in any sql database flavor:

    select
         i0.i
        +i1.i*2
        +i2.i*4
        +i3.i*8
        +i4.i*16
        +i5.i*32
        +i6.i*64
        +i7.i*128
        +i8.i*256
        +i9.i*512
        as i
    from
                   (select 0 as i union select 1) as i0
        cross join (select 0 as i union select 1) as i1
        cross join (select 0 as i union select 1) as i2
        cross join (select 0 as i union select 1) as i3
        cross join (select 0 as i union select 1) as i4
        cross join (select 0 as i union select 1) as i5
        cross join (select 0 as i union select 1) as i6
        cross join (select 0 as i union select 1) as i7
        cross join (select 0 as i union select 1) as i8
        cross join (select 0 as i union select 1) as i9
    
    0 讨论(0)
提交回复
热议问题