25

Consider this table in mysql

create table numbers (number int);
insert into numbers values (3), (2), (9);
select * from numbers;

+--------+
| number |
+--------+
|      3 |
|      2 |
|      9 |
+--------+

Is there a simple query to generate a table with the following columns

  1. The numbers from 1 till 10
  2. 1 if the number is present in the table numbers, and 0 otherwise

I guess you have to create a sequence of numbers in order to do this. If possible, I want to create such a sequence without storing it in the database.

Related question: is there a select query that generates a sequence of numbers from 1 till 10 (or 100 or 1000)?

2 Answers 2

30

IN MariaDB

MariaDB has a SEQUENCE Storage Engine. So, if you are using MariaDB, all your sequence troubles are over (or have just begun).

Sequence of 10 numbers

select * from seq_1_to_10;

NOT USING TABLES

Sequence of 10 numbers

select * from
(select 0 x union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A;

Sequence of 100 numbers

select (t*10+u+1) x from
(select 0 t union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A,
(select 0 u union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) B
order by x;

Sequence of 1000 numbers

select (h*100+t*10+u+1) x from
(select 0 h union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A,
(select 0 t union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) B,
(select 0 u union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) C
order by x;

Sequence of 10000 numbers

select (th*1000+h*100+t*10+u+1) x from
(select 0 th union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A,
(select 0 h union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) B,
(select 0 t union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) C,
(select 0 u union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) D
order by x;

USING TABLES

Sequence of 10 numbers

use test
drop table if exists seq10;
create table seq10
(x int not null auto_increment primary key);
insert into seq10 values (),(),(),(),(),(),(),(),(),();
select * from seq10;

Sequence of 100 numbers

use test
drop table if exists seq100;
create table seq100
(x int not null auto_increment primary key);
insert into seq100 values (),(),(),(),(),(),(),(),(),();
insert into seq100 values (),(),(),(),(),(),(),(),(),();
insert into seq100 values (),(),(),(),(),(),(),(),(),();
insert into seq100 values (),(),(),(),(),(),(),(),(),();
insert into seq100 values (),(),(),(),(),(),(),(),(),();
insert into seq100 select x + 50 from seq100;
select * from seq100;

Sequence of 1000 numbers

use test
drop table if exists seq1000;
create table seq1000
(x int not null auto_increment primary key);
insert into seq1000 values ();
set @p= -1;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
set @p=@p+1; insert into seq1000 select x+power(2,@p) from seq1000 where (x+power(2,@p)) <= 1000;
select * from seq1000;

Sequence of whatever numbers (Example: 3.5 million)

use test
drop table if exists seq;
create table seq
(x int not null auto_increment primary key);
insert into seq values ();
set @maxseq = 3500000;
set @p = -1;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
set @p=@p+1; insert into seq select x+power(2,@p) from seq where (x+power(2,@p)) <= @maxseq;
select max(x),count(x) from seq;

YOUR ACTUAL QUESTION

Using the sequence 0..9, you left join the sequence against the table

select A.number,1-ISNULL(B.number) present from
(select 0 number union select 1 union select 2 union select 3 union select 4 union
select 5 union select 6 union select 7 union select 8 union select 9) A
left join numbers B using (number);

Your sample data with the new query

mysql> drop table numbers;
Query OK, 0 rows affected (0.01 sec)

mysql> drop table if exists numbers;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> create table numbers (number int);
Query OK, 0 rows affected (0.02 sec)

mysql> insert into numbers values (3), (2), (9);
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> select A.number,1-ISNULL(B.number) present from
    -> (select 0 number union select 1 union select 2 union select 3 union select 4 union
    -> select 5 union select 6 union select 7 union select 8 union select 9) A
    -> left join numbers B using (number);
+--------+---------+
| number | present |
+--------+---------+
|      0 |       0 |
|      1 |       0 |
|      2 |       1 |
|      3 |       1 |
|      4 |       0 |
|      5 |       0 |
|      6 |       0 |
|      7 |       0 |
|      8 |       0 |
|      9 |       1 |
+--------+---------+
10 rows in set (0.00 sec)

mysql>

GIVE IT A TRY !!!

0
11

With MySQL 8.0, MariaDB 10.2, and later versions, you can use recursive CTEs, so:

WITH RECURSIVE nums AS (
    SELECT 1 AS value
    UNION ALL
    SELECT value + 1 AS value
    FROM nums
    WHERE nums.value <= 9
)
SELECT *
FROM nums;

You can obviously modify this to use the start value, step and end value of your choice.

As for the second question, it's then trivial to expand the above (with inspiration from part of Ronaldo's answer):

WITH RECURSIVE nums AS (
    SELECT 1 AS value
    UNION ALL
    SELECT value + 1 AS value
    FROM nums
    WHERE nums.value <= 9
)
SELECT nums.value, 1-ISNULL(numbers.number) present
FROM nums
  LEFT JOIN numbers ON numbers.number = nums.value
ORDER BY nums.value;

Note: CTEs are limited by cte_max_recursion_depth (default 1000) in MySQL, whereas in MariaDB the variable is called max_recursive_iterations (default 4294967295 prior to version 10.6.0 where it changed to 1000).

Edit:

MariaDB 10.3 introduced sequence objects (as defined in the SQL Standard and as seen in e.g. the Oracle RDBMS). These are not helpful to this particular question since the values are stored in the database, but the feature could be useful in other sequence-related use-cases.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.