I\'ve this table with the following data
Job Quantity Status Repeat
1 100 OK 2
2 400 HOLD 0
3 200 HOLD 1
4 450
DECLARE @repeats TABLE
(
rn INT NOT NULL PRIMARY KEY
);
WITH q (rn, m) AS
(
SELECT 1, MAX(repeat) + 1
FROM jobs
UNION ALL
SELECT rn + 1, m
FROM q
WHERE rn < m
)
INSERT
INTO @repeats
SELECT rn
FROM q
SELECT j.*
FROM jobs j
CROSS APPLY
(
SELECT TOP (j.repeat + 1)
NULL
FROM @repeats
) q (repeat)
If you have a table which guaranteedly has more records than the maximum possible value of repeat
, you may get rid of @repeats
and use that table instead.
This will support over 7,400 repeats for any individual job (on my system). If you need more, you can use a different system table or a cross join.
DECLARE @d TABLE (Job INT, Quantity INT, Status VARCHAR(12), Repeat INT);
INSERT @d SELECT 1, 100, 'OK' ,2
UNION ALL SELECT 2, 400, 'HOLD',0
UNION ALL SELECT 3, 200, 'HOLD',1
UNION ALL SELECT 4, 450, 'OK' ,3;
WITH x AS
(
SELECT TOP (SELECT MAX(Repeat)+1 FROM @d) rn = ROW_NUMBER()
OVER (ORDER BY [object_id])
FROM sys.all_columns
ORDER BY [object_id]
)
SELECT * FROM x
CROSS JOIN @d AS d
WHERE x.rn <= d.Repeat + 1
ORDER BY Job;
You may write stored procedure which will do this query (as cursor) and then you may fill new temporary table as you want
CREATE FUNCTION [dbo].[GetRepeatJobs]()
RETURNS
@JobsRepeatTable TABLE (JobId int, JobName nchar(10))
AS
BEGIN
DECLARE @i int
DECLARE @j int
DECLARE @JobId int
DECLARE @JobName nchar(10)
DECLARE JobsCursor CURSOR FOR (select JobId, JobName, JobRepeat from jobs)
OPEN JobsCursor
FETCH NEXT FROM JobsCursor INTO @JobId, @JobName, @i
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT @j = 0
WHILE @j < @i
BEGIN
INSERT INTO @JobsRepeatTable VALUES (@JobId, @JobName)
SELECT @j = @j+1
END
FETCH NEXT FROM JobsCursor INTO @JobId, @JobName, @i
END
RETURN
END
Works perfect for me.
I prefer the below approach, as it is not reliant on external data for the query to be successful and is fairly straight forward. I've used Aaron Bertrand's code to initialize the data table but my approach on how to repeat data - this approach does not require a specific table to contain more rows than the required recursions / not dependent on external data.
DECLARE @d TABLE (Job INT, Quantity INT, Status VARCHAR(12), Repeat INT);
INSERT @d SELECT 1, 100, 'OK' , 2
UNION ALL SELECT 2, 400, 'HOLD', 0
UNION ALL SELECT 3, 200, 'HOLD', 1
UNION ALL SELECT 4, 450, 'OK' , 3;
DECLARE @maxRecursion INT;
SET @maxRecursion = (SELECT MAX(Repeat)
FROM @d);
WITH Iterator AS
(
SELECT 1 AS Iterations
UNION ALL
SELECT Iterations + 1 FROM Iterator WHERE Iterations < @maxRecursion
)
SELECT A.*
FROM @d AS A
RIGHT JOIN Iterator ON Iterator.Iterations <= (A.Repeat + 1)
ORDER BY Job ASC
OPTION (MAXRECURSION 0)
Cheers!