The first place I came across using a numbers table was from a Joe Celko book. I take a slightly different approach, typically using a view (with the following CTE) to generate the numbers.
WITH
I AS (SELECT iNbr = 0 UNION SELECT iNbr = 1 UNION
SELECT iNbr = 2 UNION SELECT iNbr = 3 UNION
SELECT iNbr = 4 UNION SELECT iNbr = 5 UNION
SELECT iNbr = 6 UNION SELECT iNbr = 7 UNION
SELECT iNbr = 8 UNION SELECT iNbr = 9 ),
X AS (SELECT iNbr = I.iNbr * 10 FROM I ),
C AS (SELECT iNbr = I.iNbr * 100 FROM I ),
M AS (SELECT iNbr = I.iNbr * 1000 FROM I ),
N AS (
SELECT iNbr = I.iNbr + X.iNbr + C.iNbr + M.iNbr
FROMI
CROSS JOIN X
CROSS JOIN C
CROSS JOIN M
)
SELECTiNbr
FROMN
ORDER BY iNbr
I started running into places where I needed the numbers on different servers, with different ranges, etc. I ended up using something like this (above) instead of a table. I do not have any reference as to performance or speed, but it does work quickly in my environment.
Beer's Law: Absolutum obsoletum
"if it works it's out-of-date"