I would like to have an sql statement that would return me a simple sequence
of numbers, something like this:
SELECT * FROM GenerateSequence(1, 4) would simply return
1
2
3
4
I need this to be part of a user defined function so a loop, temp table etc
is no good. I thought maybe there was something new in sql2005 that was
built in for this but couldn't find anything. I need this for various
reasons that have cropped up over the years. I've implemented something
using a recursive CTE but it's not perfect as it errors at a certain limit
and is slow.
Thanks for any replies,
Michael
You can create a numbers table and select from it or use a CTE just
like you did. The CTE has limitations on number of recursion, but you
can use the maxrecursion hint to change or even cancel the limitation
(not that it is recommended that you’ll call the recursion so many
times).
Adi
CREATE FUNCTION GenerateSequence (@start INT, @end INT)
RETURNS TABLE
AS
RETURN
WITH
Num1 (n) AS (SELECT 1 UNION ALL SELECT 1),
Num2 (n) AS (SELECT 1 FROM Num1 AS X, Num1 AS Y),
Num3 (n) AS (SELECT 1 FROM Num2 AS X, Num2 AS Y),
Num4 (n) AS (SELECT 1 FROM Num3 AS X, Num3 AS Y),
Num5 (n) AS (SELECT 1 FROM Num4 AS X, Num4 AS Y),
Num6 (n) AS (SELECT 1 FROM Num5 AS X, Num5 AS Y),
Nums (n) AS
(SELECT ROW_NUMBER() OVER(ORDER BY n)
FROM Num6)
SELECT n FROM Nums
WHERE n BETWEEN @start AND @end;
GO
SELECT n FROM GenerateSequence(1, 4);
--
Plamen Ratchev
http://www.SQLStudio.com
This seems to work pretty well. I thought it had problems but it looks like
the server was just bogged down doing other work. Any comments? The Level
column is only really shown for debug purposes.
Cheers,
Michael
usage:
SELECT * FROM dbo.udfSequence(1000)
ALTER FUNCTION [dbo].[udfSequence]
(@MaxValue INT)
RETURNS TABLE
AS
RETURN
WITH SEQ_INNER AS
(
SELECT 1 AS [Value]
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
UNION ALL
SELECT 10
),
CTE AS
(
SELECT [Value], 1 AS LEVEL FROM SEQ_INNER WHERE [Value] <= @MaxValue
UNION ALL
SELECT CTE.[Value] * 10 + SEQ_INNER.VALUE, LEVEL + 1
FROM CTE
CROSS JOIN SEQ_INNER
WHERE CTE.[Value] * 10 + SEQ_INNER.VALUE <= @MaxValue
)
SELECT TOP 2147483647 [Value], LEVEL FROM CTE ORDER BY [Value]
Thanks, I have emailed this to myself and will look at it on monday as I'm
just leaving for the weekend now.
Cheers,
Michael
Hey that works really well, it's faster and simpler than my routine and as
you said very efficient. The question I have is why? It appears to create 4
billion rows even if you only filter out 4.
Michael
NO! you think like a procedural programmers, not an SQL programmer.
SQL does best with tables and joins.
go 1000
select * from t where...
"Michael C" <mi...@nospam.com> wrote in message
news:OIGh3dcV...@TK2MSFTNGP03.phx.gbl...
INSERT INTO tbl DEAFULT VALUES
GO 1000
"Uri Dimant" <ur...@iscar.co.il> wrote in message
news:%23xacgpf...@TK2MSFTNGP02.phx.gbl...
--
Kevin G. Boles
Indicium Resources, Inc.
SQL Server MVP
kgboles a earthlink dt net
"Michael C" <mi...@nospam.com> wrote in message
news:er2WwTeV...@TK2MSFTNGP06.phx.gbl...
SET STATISTICS TIME ON;
SELECT n FROM GenerateSequence(1, 4);
SELECT n FROM GenerateSequence(100000001,100000004);
Here's a minor modification:
CREATE FUNCTION dbo.IntSequence (@start INT, @end INT)
RETURNS TABLE AS
RETURN
WITH
N1 (n) AS (SELECT 1 UNION ALL SELECT 1),
N2 (n) AS (SELECT 1 FROM N1 AS x, N1 AS y),
N3 (n) AS (SELECT 1 FROM N2 AS x, N2 AS y),
N4 (n) AS (SELECT 1 FROM N3 AS x, N3 AS y),
N5 (n) AS (SELECT 1 FROM N4 AS x, N4 AS y),
N6 (n) AS (SELECT 1 FROM N5 AS x, N5 AS y),
Nx (n) AS (SELECT ROW_NUMBER() OVER(ORDER BY n) FROM N6)
SELECT @start - 1 + n AS n
FROM Nx
WHERE n <= @end - @start + 1;
GO
SET STATISTICS TIME ON;
SELECT n FROM dbo.IntSequence(1, 4);
SELECT n FROM dbo.IntSequence(100000001,100000004);
"Plamen Ratchev" <Pla...@SQLStudio.com> wrote in message
news:vM2dnfpcC5hYTKrU...@speakeasy.net...