In these cases, a performatic solution is to use generators. The initial solution works on virtually any DBMS with SQL support. See more at the end of the answer solutions optimized for specific Dbms.
Here is an example that produces numbers from 0 to 999:
SELECT d1+d2*10+d3*100 AS gerador FROM
( SELECT 0 AS d1 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 ) t1,
( SELECT 0 AS d2 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 ) t2,
( SELECT 0 AS d3 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 ) t3
See working on SQL Fiddle.
Functioning:
Each of the SELECT 0 AS d1 UNION SELECT 1 ... SELECT 9
generates numbers from 0 to 9;
what we did in the initial example was to match 3 of them, to have 3 decimal places. The formula d1+d2*10+d3*100
serves to convert the 3 outputs of each generator into an integer number.
Depending on the DBMS it may be necessary to use UNION ALL
instead of just UNION
.
Optimizing for more specific uses:
If you need numbers from 1 to 780, just adjust the formula and use a LIMIT 780
, for example.
nothing prevents multiplication by changing the scale in the Queries:
SELECT d1 + d2 AS gerador FROM
( SELECT 0 AS d1 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 ) t1,
( SELECT 0 AS d2 UNION SELECT 10 UNION SELECT 20 UNION SELECT 30 UNION SELECT 40
UNION SELECT 50 UNION SELECT 60 UNION SELECT 70 UNION SELECT 80 UNION SELECT 90 ) t2
In this example the second set of SELECT
s is optimized with the numbers * 10 now.
if you need numbers from 0 to 255, it is much better to use a shorter query:
SELECT d1+d2*4+d3*16+d4*64 AS gerador FROM
( SELECT 0 AS d1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) t1,
( SELECT 0 AS d2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) t2,
( SELECT 0 AS d3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) t3,
( SELECT 0 AS d4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3) t4
In this case the logic was as follows: 4 4 = 256, so we use 4 darlings, but with 4 digits in each. The important thing is to understand the operation of the generator, because there are several ways to optimize the code.
Generating dates
We can restrict the third digit of the initial example to only 3, because 0 to 399 is enough to cover an entire year. DATE_ADD is a solution to generate a date:
DATE_ADD( '2014-01-01', INTERVAL d1+d2*10+d3*100 DAY )
and all it takes is one WHERE
to restrict output to a one-year interval. See another question that you mentioned a reply with the full example.
Proprietary solutions:
MS SQL Server
In MS SQL Server we have to simplify a bit using a function. Note the caution to limit recursion with MAXRECURSION 0
:
WITH gerador (id) AS (
SELECT 1
UNION ALL
SELECT id + 1
FROM gerador
WHERE id < 1000000
)
SELECT TOP 1000 id FROM gerador
OPTION ( MAXRECURSION 0 )
GO
See working on SQL Fiddle.
Postgresql
Even simpler, with the function generate_series
:
SELECT * FROM generate_series ( 1, 1000 )
See working on SQL Fiddle.
Oracle
Oracle has a standard installation special table called dual, with a series of pseudo-columns for special uses. Example for our question:
SELECT level FROM dual CONNECT BY level < 1000
See working on SQL Fiddle.
Complementing:
Initially the question puts the condition of not having a table for it. Anyway, an intermediate solution, but very interesting if these sequences are needed on many occasions, is you have a table of integers:
CREATE TABLE inteiros (i INT);
INSERT INTO inteiros (i) VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
Thus, you can use the above techniques by combining this table in place of the SELECT UNION
:
SELECT d3.i*100+d2.i*10+d1.i+1 AS gerador
FROM inteiros AS d1
JOIN inteiros AS d2
JOIN inteiros AS d3;
So I can conclude that in Mysql or Sqlite the solution would have to be the most general?
– Maniero
@bigown unfortunately in Mysql I still need the same initial generic solution (I say this, because I use Mysql a lot in practice). In Sqlite the thing can get more interesting: if the chosen implementation is Embedded, it is relatively simple to implement a native function similar to Postgresql. If using a third-party connector, the generic solution solves. Remembering that despite the query being "bulky", the performance of the generic solution is very good.
– Bacco