Dynamic Generate rows without using loops - sql

How to dynamic generate row from max value
for example if i am passing max value 7 Store procedure should return value
1
2
3
4
5
6
7
without using loops

If you are using sql server below query will serve you purpose:
create procedure generate_list
#maxLimit int
as
begin
SELECT DISTINCT n = number
FROM master..[spt_values]
WHERE number BETWEEN 1 AND #maxlimit
end
Then call the store procedure with :
exec generate_list 7
Output:

create PROCEDURE [dbo].GenerateSequence
#MaxLimit int
AS
BEGIN
;with numcte
AS
(
SELECT 1 [Sequence]
UNION all
SELECT [Sequence] + 1 FROM numcte WHERE [Sequence] < #MaxLimit
)
select * from numcte
END

Related

How to get Output parameter from a column in table for a stored procedure

I've stored procedure like this:
create procedure sp_testsp
(
#vc_order_by varchar(100),
#int_start_index INT,
#int_grid_size INT,
#count bigint output
)
as
begin
select * from
(select ROW_NUMBER() over
(order by
case #vc_order_by = '' then tab1.int_id end desc) AS row,
*,
COUNT(tab1.int_id) OVER() as totalRowCount
from
(select * from tbl_test) tab1) tab2
where row BETWEEN CONVERT(VARCHAR, #int_start_index) and CONVERT(VARCHAR,(#int_start_index-1) + #int_grid_size);
set #count = 0;
end
We can execute the above stored procedure by:
DECLARE #size bigint;
EXEC sp_testsp '', 1,5, #size output;
SELECT #size;
The written sp provides data based on pagination and we can retrieve 100 or any number of records by passing a number in #int_grid_size .
The table output looks like following:
row int_id vc_name totalRowCount
1 5 a 107
2 6 ab 107
3 7 abc 107
4 8 abcd 107
5 10 abcc 107
The last column gives the total records count of the table or total record if we use where condition.
I want to OUTPUT any one column value of the totalRowCount in '#count' in the stored procedure.
I cannot use ##ROWCOUNT as it only sends the count of records the sp is outputting i.e in this case 5 but actual records are 107.
Just wondering if there is any way. Any help is apperciated. Thanks.
Edit:
I tried something like this, and it works:
create procedure sp_testsp
#param1 nvarchar(800),
#count bigint output
as
begin
select * from tbl_test tt where tt.col1 = #param1;
set #count = select Count(*) from tbl_test tt where tt.col1 = #param1;
end
The issue with this is I've to call the query once and then call the query again for #count. This is working but taking lot of time for big queries.
You can do that by temp table
select * into #temp from
(select ROW_NUMBER() over
(order by
case #vc_order_by = '' then tab1.int_id end desc) AS row,
*,
COUNT(tab1.int_id) OVER() as totalRowCount
from
(select * from tbl_test) tab1) tab2
where row BETWEEN CONVERT(VARCHAR, #int_start_index) and CONVERT(VARCHAR,(#int_start_index-1) + #int_grid_size);
select top 1 #count=totalRowCount from #temp
select * from #temp --you can exclude totalRowCount

Difference between two columns into separate rows for each value between the two

I'm having trouble explaining my problem but I have this table
ID START END
1 10 12
2 30 31
3 11 13
and want something like this:
ID NUMBER
1 10
1 11
1 12
2 30
2 31
3 11
3 12
3 13
I need the all unique whole numbers between the two columns transform into separate rows.
Here's how I want the transformation to look like
I haven't tried anything because I don't even know how to call such procedure so any help is appreciated
If you don't have a numbers table (highly recommended), you can use an ad-hoc tally table in concert with a CROSS APPLY
Example
Select A.ID
,B.Number
From YourTable A
Cross Apply ( Select Top ([End]-[Start]+1)
Number=[START]-1+Row_Number() Over (Order By (Select NULL))
From master..spt_values n1, master..spt_values n2
) B
Returns
ID Number
1 10
1 11
1 12
2 30
2 31
3 11
3 12
3 13
In SQL Server, you can use a recursive CTE:
with cte as (
select id, [start] as number, [end] as end_number
from t
union all
select id, number + 1
from cte
where number < end_number
)
select id, number
from cte;
Note: If the span can exceed 100, you need option (maxrecursion) for the query.
Recursive CTEs are usually a bit slower than a numbers table. However, I find them much faster than I would expect.
--create table NewTable
--(
--ID int,
--NUMBER int
--)
DECLARE #ID nvarchar(50)
declare #START int
declare #END int
DECLARE Cursor_Name CURSOR
FOR
select ID, [START], [End] from tblSequences
OPEN Cursor_Name
FETCH NEXT FROM Cursor_Name INTO #ID,#START,#END
WHILE ##FETCH_STATUS = 0
begin
WHILE #START<=#END
begin
insert into NewTable (ID, NUMBER) Values (#ID, #START)
set #START = #START+1
end
FETCH NEXT FROM Cursor_Name INTO #ID,#START,#END
end
CLOSE Cursor_Name
DEALLOCATE Cursor_Name
select * from NewTable

In SQL , how to build a loop that copies a row number of times

could someone please help? My starting table looks like this with 2 fields:
Name Counter
dave 2
Joe 3
I want my result to look like this:
Name Counter
dave 1
dave 2
joe 1
joe 2
joe 3
Essentially creating n number of records base on the counter and starts at 1. I tried to do a loop using counter as a variable, but the code just runs nonstop.. could someone help?
A procedural SQL Server solution:
declare #input table
(
name nvarchar(100)
,wantedrows int
,processed bit
,id uniqueidentifier
);
declare #output table
(
name nvarchar(100)
,rownum int
);
insert into #input
select 'Dave',3,0,newid()
union
select 'Joe',2,0,newid();
while exists(select * from #input where processed = 0)
begin
declare #currentid uniqueidentifier = (select top 1 id from #input where processed = 0);
declare #currentwantedrows int = (select wantedrows from #input where id = #currentid);
declare #i int = 0;
while #i < #currentwantedrows
begin
insert into #output
select name,#i+1
from #input
where id = #currentid;
set #i = #i + 1;
end;
update #input set processed = 1 where id = #currentid;
end
select name,wantedrows from #input;
select * from #output;
You can use a number-table or following trick using a system view to build a sequence:
WITH Nums AS
(
SELECT n = ROW_NUMBER() OVER (ORDER BY [object_id])
FROM sys.all_objects
)
SELECT Name, Counter = n
FROM Nums n CROSS JOIN Table1 t1
WHERE n BETWEEN 1 AND Counter
ORDER BY Name, Counter;
Demo
This view has only about 2000 rows, so if you need more you could use a number-table.
http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1
( presuming SQL-Server )
Is a hundred copies enough?
create table #c (num)
insert into #c (num)
select 0 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
select T.Name, c1.num * 10 + c0.num + 1
from T, #c c1, #c c0
where c1.num * 10 + c0.num < T.Counter
drop table #c
You didn't say which version of Sybase. The old ones I've worked on didn't allow derived tables so I had to throw the values into a temp table. But you can see how to extend the idea. This may not be the best approach if this is something you need to do more than once though.

How to generate Fibonacci Series [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
How to Generate Fibonacci series in sql !
I need to generate Fibonacci series 0 1 1 2 3 5 8 13 21 ... N
I did this easily using C-code I need to do this using Sql !
Try This Simple Query:
1) For Result In Row-by-Row (Single Column, Multiple Rows)
WITH Fibonacci (PrevN, N) AS
(
SELECT 0, 1
UNION ALL
SELECT N, PrevN + N
FROM Fibonacci
WHERE N < 1000000000
)
SELECT PrevN as Fibo
FROM Fibonacci
OPTION (MAXRECURSION 0);
Output 1:
2) For Result in Only One Row (Comma sepreted, in Single Cell)
WITH Fibonacci (PrevN, N) AS
(
SELECT 0, 1
UNION ALL
SELECT N, PrevN + N
FROM Fibonacci
WHERE N < 1000000000
)
SELECT Substring(
(SELECT cast(', ' as varchar(max)) + cast(PrevN as varchar(max)
);
FROM Fibonacci
FOR XML PATH('')),3,10000000) AS list
Output 2:
Try this !
declare #a int
declare #b int
declare #c int
Declare #i int
set #a=0
set #b=1
set #i=0
set #c=0
Print 'Fibonacci Series'
print #a
print #b
while #i<10
Begin
set #c=#a+#b
print #c
set #i=#i+1
set #a=#b
set #b=#c
end
Outputs !
Fibonacci Series
0
1
1
2
3
5
8
13
21
34
55
89
Please try:
SELECT 0 AS fib_number UNION ALL
SELECT
FLOOR(POWER(( 1 + SQRT(5) ) / 2.0, number) / SQRT(5) + 0.5)
FROM master..spt_values
WHERE TYPE = 'p' AND number BETWEEN 1 AND 70
Try this :-
Declare #Fib int = 5
;with cte as
(
Select 0 as Previous,1 as Next ,0 as Level
union all
Select Next,Next + Previous,Level +1 from cte
where Level +1 <#Fib
)
Select Previous as FibonacciSeries from cte
This is for generating the first 10 numbers in the series.
DECLARE #NoOne INT, #NoTwo INT
DECLARE #FibonacciTable TABLE (Number INT NOT NULL)
--Insert first two numbers 0 and 1
INSERT #FibonacciTable (Number) SELECT 0 UNION ALL SELECT 1
SELECT #NoOne = 0, #NoTwo = 1
WHILE (SELECT COUNT(*) FROM #FibonacciTable) < 10
BEGIN
INSERT #FibonacciTable (Number) VALUES(#NoOne + #NoTwo)
SELECT #NoTwo = #NoOne + #NoTwo, #NoOne = #NoTwo - #NoOne
END
SELECT * FROM #FibonacciTable
GO
CREATE TABLE #Fibonacci (value BIGINT)
GO
INSERT INTO #Fibonacci(value) SELECT 0
INSERT INTO #Fibonacci(value) SELECT 1
SELECT * FROM #Fibonacci
GO
INSERT INTO #Fibonacci(value)
SELECT SUM(value) FROM ( SELECT TOP 2 * FROM #Fibonacci ORDER BY value DESC ) AS value
GO 10 -- Loop insert 10 value...
SELECT * FROM #Fibonacci
DROP TABLE #Fibonacci
Result Code

Creating a range of numbers in an sql subquery

Is there a better way to generate a range of numbers in SQL than below? I'm using MySql.
SELECT tens.x + ones.x + 1
FROM
(SELECT 0 x UNION ALL
SELECT 1 x UNION ALL
SELECT 2 x UNION ALL
...
SELECT 9 x ) ones
CROSS JOIN
(SELECT 0 x UNION ALL
SELECT 10 x UNION ALL
SELECT 20 x UNION ALL
...
SELECT 90 x ) tens;
A common way to do that in Oracle is to abuse the rownum pseudocolumn:
select rownum from all_objects where rownum<=100;
Using Sql server 2005+ you can make use of CTEs
DECLARE #Start INT, #End INT
SELECT #Start = 0, #End = 100000
;WITH Numbers AS (
SELECT #Start Num
UNION ALL
SELECT Num + 1
FROM Numbers
WHERE Num < #End
)
SELECT *
FROM Numbers
OPTION (MAXRECURSION 0);
PostgreSQL allows you to use:
select * from generate_series(2,4);
generate_series
-----------------
2
3
4
That is specific for the PostgresSQL engine. But it shouldn't be to hard to write a stored proedure for your data base.
Why not loop? like
BEGIN
DECLARE a INT Default 0 ;
simple_loop: LOOP
SET a=a+1;
insert into mytable(id) values(a);
IF a=1000 THEN
LEAVE simple_loop;
END IF;
END LOOP simple_loop;
Modified from Mysql For Loop
Pardon me if the syntax is wrong as I am a pure SQL SERVER guy(: