Generate an integer sequence in MySQL

前端 未结 16 2699
南旧
南旧 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:32

    There is a way to get a range of values in a single query, but its a bit slow. It can be sped up by using cache tables.

    assume you want a select with a range of all BOOLEAN values:

    SELECT 0 as b UNION SELECT 1 as b;
    

    we can make a view

    CREATE VIEW ViewBoolean AS SELECT 0 as b UNION SELECT 1 as b;
    

    then you can do a Byte by

    CREATE VIEW ViewByteValues AS
    SELECT b0.b + b1.b*2 + b2.b*4 + b3.b*8 + b4.b*16 + b5.b*32 + b6.b*64 + b7.b*128 as v FROM
    ViewBoolean b0,ViewBoolean b1,ViewBoolean b2,ViewBoolean b3,ViewBoolean b4,ViewBoolean b5,ViewBoolean b6,ViewBoolean b7;
    

    then you can do a

    CREATE VIEW ViewInt16 AS
    SELECT b0.v + b1.v*256 as v FROM
    ViewByteValues b0,ViewByteValues b1;
    

    then you can do a

    SELECT v+MIN as x FROM ViewInt16 WHERE v

    To speed this up I skipped the auto-calculation of byte values and made myself a

    CREATE VIEW ViewByteValues AS
    SELECT 0 as v UNION SELECT 1 as v UNION SELECT ...
    ...
    ...254 as v UNION SELECT 255 as v;
    

    If you need a range of dates you can do.

    SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE v

    or

    SELECT DATE_ADD('start_date',v) as day FROM ViewInt16 WHERE day<'end_date';
    

    you might be able to speed this up with the slightly faster MAKEDATE function

    SELECT MAKEDATE(start_year,1+v) as day FRON ViewInt16 WHERE day>'start_date' AND day<'end_date';
    

    Please note that this tricks are VERY SLOW and only allow the creation of FINITE sequences in a pre-defined domain (for example int16 = 0...65536 )

    I am sure you can modify the queries a bit to speed things up by hinting to MySQL where to stop calculating ;) (using ON clauses instead of WHERE clauses and stuff like that)

    For example:

    SELECT MIN + (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) FROM
    ViewByteValues b0,
    ViewByteValues b1,
    ViewByteValues b2,
    ViewByteValues b3
    WHERE (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) < MAX-MIN;
    

    will keep your SQL server busy for a few hours

    However

    SELECT MIN + (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) FROM
    ViewByteValues b0
    INNER JOIN ViewByteValues b1 ON (b1.v*256<(MAX-MIN))
    INNER JOIN ViewByteValues b2 ON (b2.v*65536<(MAX-MIN))
    INNER JOIN ViewByteValues b3 ON (b3.v*16777216<(MAX-MIN)
    WHERE (b0.v + b1.v*256 + b2.v*65536 + b3.v*16777216) < (MAX-MIN);
    

    will run reasonably fast - even if MAX-MIN is huge as long as you limit the result with LIMIT 1,30 or something. a COUNT(*) however will take ages and if you make the mistake of adding ORDER BY when MAX-MIN is bigger than say 100k it will again take several seconds to calculate...

提交回复
热议问题