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 4 years ago.
Improve this question
Want to find sum of digits of factorial of a num?
But i need the sum of the result like 5! is 120
in this i want 1+2+0=3
This can be achieved with help of recursive CTE:
--here you decide what factorial to calculate
declare #i int = 5;
;with cte as(
select 1 n, 1 factorial
union all
select n + 1, factorial * (n + 1) from cte
where n < #i
)
select factorial,
--just to make sure we correctly sum all digits
(factorial%100000)/10000 +
(factorial%10000)/1000 +
(factorial%1000)/100 +
(factorial%100)/10 +
factorial%10 DigitsSum
from cte
where n = #i
You can use code like this:
declare #a int
set #a = 120
declare #temp varchar(20)
set #temp = cast(#a as varchar(20))
declare #Result int
set #Result = 0
declare #tempLength int
set #tempLength = DATALENGTH(#temp)
while #tempLength > 0
begin
set #Result = #Result + cast(SUBSTRING(#temp, #tempLength, 1) as int)
set #tempLength = #tempLength - 1
end
select #Result
Variable "a" is same your factorial result.
try substring() function and separate the digits and then add all togather.
You can Create a function from sum of factorial of the no To Find out the Factorial of a number.
Then use below query to find the Sum:
DECLARE #var1 int
select #var1 = dbo.Factorial(5)
;WITH i AS (
SELECT #var1 / 10 n, #var1 % 10 d
UNION ALL
SELECT n / 10, n % 10
FROM i
WHERE n > 0
)
SELECT SUM(d)
FROM i;
Related
This question is about generating N random numbers whose sum is M(constant) using SQL.
For example we have a number M=9.754. We need 10 random numbers whose sum is 9.754.
It should be done in SQL Server environment.
Can anybody help me?
While the #Squirrel answer is interesting but numbers here is more random
here is the code:
DECLARE #s INT=1,
#k FLOAT=0,
#final FLOAT=9.917,
#sum FLOAT =0,
#min FLOAT=1,
#max FLOAT=9.917
BEGIN
WHILE (#sum <> #final)
BEGIN
WHILE (#s <= 10)
BEGIN
SET #k =
(
SELECT ROUND(RAND(CHECKSUM(NEWID())) * (#max - #min) + #min,3)
);
PRINT (CONCAT('random: ',#k));
IF(#sum+#k <=#final)
SET #sum+=#k;
SET #max=#final-#sum;
PRINT (CONCAT('computed sum: ',#k));
IF(#max>1) SET #min=1 ELSE SET #min=0;
IF(#sum=#final)
BREAK;
SET #s = #s + 1;
SET #k = #k + 0;
END;
PRINT (CONCAT('final', #final))
PRINT (CONCAT('sum', #sum))
IF(#sum<>#final)--force stop if after 10 try the sum not match with final
BEGIN
PRINT(CONCAT('final random number:',#final-#sum))
SET #sum=#final;
END;
SET #s=0;
IF(#sum=#final)
BEGIN
PRINT('****************************DONE****************************')
BREAK;
END
END;
PRINT ('end');
END;
Interesting requirement.
Query below uses tally table / number table to generate 10 random numbers after that find the ratio. Final query check for case where sum of the numbers is not equal to #m and make the adjustment on the biggest number.
declare #m decimal(10,3) = 9.754,
#n int = 10;
with
-- using recursive CTE to generate a number table
numbers as
(
select n = 1
union all
select n = n + 1
from numbers
where n < #n
),
-- generate random positive numbers using newid()
-- Note : 100 is chosen arbitrary
num as
(
select n = abs(checksum(newid())) % 100
from numbers
),
-- calculate the ratio
ratio as
(
select r,
rn = row_number() over (order by r desc),
sum_r = sum(r) over()
from
(
select r = convert(decimal(10,3), n * 1.0 / sum(n) over() * #m)
from num
) r
)
-- sum(r) may not equal to #m due to rounding
-- find the difference and adjust it to the biggest r
select r, rn, sum_r,
adj_r = r + case when rn = 1 then #m - sum_r else 0 end,
sum_adj_r = sum(r + case when rn = 1 then #m - sum_r else 0 end) over()
from ratio
dbfiddle demo
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I need a query which prints rows by the n number represented against it. example
You haven't specified your DBMS, the following solution will work for PostgreSQL:
select t.nr
from generate_series(1,4) as t(nr)
cross join generate_series(1,t.nr)
order by t.nr;
With 100% standard ANSI SQL, you can do this:
with recursive numbers (nr) as (
select * from (values (1) ) as t
union all
select p.nr + 1
from numbers p
where p.nr + 1 <= 4
)
select t.*
from numbers t
join numbers t2 on t2.nr <= t.nr
order by t.nr;
SQL Server
declare #n int = 5; // your n value
declare #i int = 1;
declare #j int = 1;
declare #tmp table (val int)
WHILE (#i <= #n)
BEGIN
WHILE (#j <= #i)
BEGIN
insert into #tmp(val) values(#i)
set #j = #j + 1;
END
set #j = 1;
set #i = #i + 1;
END
select * from #tmp
I want is to select Armstrong numbers from the list below list I have searched of solution of this question bu unable to find in SQL-Server:
Numbers
121
113
423
153
541
371
I am sure most of you know what's the Armstrong number and how to calculate though I am describing is for the simplicity : sum of the cubes of its digits is equal to the number itself i.e.
1*1*1 + 5*5*5 + 3*3*3 = 153
3*3*3 + 7*7*7 + 1*1*1 = 371
Please help me on this as I am also trying but seeking for quick solution. It will be very helpful to me. Thanks in advance.
Obviously static processing during each query is not correct approach but we can create function like this and
create function dbo.IsArmstrongNumber(#n int)
returns int as
begin
declare #retValue int = 0
declare #sum int = 0
declare #num int = #n
while #num > 0
begin
set #sum += (#num%10) * (#num%10) * (#num%10)
set #num = #num/10
end
IF #sum = #n
set #retValue = 1
return #retValue
end
Pre-processing and selecting in IN clause is better
select * from #Numbers where dbo.IsArmstrongNumber(n) = 1
select 153 x into #temp;
insert #temp values(371);
insert #temp values(541);
with cte as (select x, substring(cast(x as nvarchar(40)) ,1,1) as u, 1 as N FROM #temp
union all
select x, substring(cast(x as nvarchar(40)),n+1,1) as u , n+1 from cte where len(cast(x as nvarchar(40))) > n
)
select x from cte group by x having SUM(POWER(cast(u as int),3)) = x
drop table #temp;
here is the mark 2 - you can change the #ORDER to explore power of 4,5 etc
declare #order int = 3;
declare #limit int = 50000;
with nos as (select 1 no
union all
select no + 1 from nos where no < #limit),
cte as (select no as x, substring(cast(no as nvarchar(40)) ,1,1) as u, 1 as N FROM nos
union all
select x, substring(cast(x as nvarchar(40)),n+1,1) as u , n+1 from cte where len(cast(x as nvarchar(40))) > n
)
select x from cte group by x having SUM(POWER(cast(u as int),#order)) = x
option (maxrecursion 0);
This is a quick mod to my sum of digits UDF
Declare #Table table (Numbers int)
Insert into #Table values
(121),
(113),
(423),
(153),
(541),
(371)
Select * from #Table where [dbo].[udf-Stat-Is-Armstrong](Numbers)=1
Returns
Numbers
153
371
The UDF
CREATE Function [dbo].[udf-Stat-Is-Armstrong](#Val bigint)
Returns Bit
As
Begin
Declare #RetVal as bigint
Declare #LenInp as bigint = len(cast(#Val as varchar(25)))
;with i AS (
Select #Val / 10 n, #Val % 10 d
Union ALL
Select n / 10, n % 10
From i
Where n > 0
)
Select #RetVal = IIF(SUM(power(d,#LenInp))=#Val,1,0) FROM i;
Return #RetVal
End
You can use the following to find Armstrong numbers using Sql functions:
WITH Numbers AS(
SELECT 0 AS number UNION ALL SELECT number + 1 FROM Numbers WHERE number < 10000)
SELECT number AS ArmstrongNumber FROM Numbers
WHERE
number = POWER(COALESCE(SUBSTRING(CAST(number AS VARCHAR(10)),1,1),0),3)
+ POWER(COALESCE(SUBSTRING(CAST(number AS VARCHAR(10)),2,1),0),3)
+ POWER(COALESCE(SUBSTRING(CAST(number AS VARCHAR(10)),3,1),0),3)
OPTION(MAXRECURSION 0)
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
I'm writing a query, part of Stored Procedure in SQL Server. I need to find cumulative summation in SQL Server.
A variable will hold a integer value say 100. Let's say
Declare #Variable int = 100
Now the #NewVariable will have below formula:
#NewVariable = #Variable * (1 - 0.005)
Hence #NewVariable = 99.5
Now, the #NewestVariable will have below formula;
#NewestVariable = #NewVariable * (1 - 0.005)
Hence the #NewestVariable will have value of 99.00
Likewise this calculation will occur 24 times and all the results will be sum at the end.
Hence final result will be: 100 + 99.5 +99.00 + .... ...
I tried to achieve the desired result using #Count Variable (DECLARE #COUNT INT = 24) and using a While loop, but I'm not sure whether I'm correct or not?
Request your help!
Thanks!
You can do it using a CTE as below:
declare #variable int = 100
;with cte as
(
select convert(numeric(8,2), #variable) as var, 1 as recCount
union all
select convert(numeric(8,2), #variable * (1 - recCount*0.005)) as var, recCount+1 as recCount
from cte
where recCount < 24
)
select sum(var) as total from cte
Working Fiddle Demo
Edit: Adjusted to resolve rounding error as per #peter.petrov 's comment
If you need to get the values of each row before counting, please use this fiddle
Try this code.
declare #Variable decimal(20,10);
set #Variable = 100;
declare #Sum decimal(20,10);
set #Sum = 0;
declare #cnt int;
set #cnt = 1;
while (#cnt <= 24)
begin
set #Sum = #Sum + #Variable;
set #Variable = #Variable * (1.0 - 0.005);
set #cnt = #cnt + 1;
end;
select #Sum;
A simple answer would be like this
DECLARE #Variable INT = 100
SELECT #Variable
DECLARE #counter INT = 1
DECLARE #SumVariable NUMERIC(20,2) = #Variable
DECLARE #NewVariable NUMERIC(20,2) = #Variable
WHILE(#counter<24)
BEGIN
SET #NewVariable = #NewVariable * 0.995
SET #SumVariable = #SumVariable + #NewVariable
SET #counter = #counter+1
END
SELECT #SumVariable
You could also use a "quirky update" to avoid while-loops. If you're not interesed in intermediate resuls, just modify the last code line to select only the max(total).
DECLARE #total DECIMAL(10,3) = 0.000
;WITH "data" AS
(
SELECT CAST( 100 AS DECIMAL(10,3)) AS id
UNION ALL
SELECT CAST( id * ( 1 - 0.005 ) AS DECIMAL(10,3)) FROM "data" WHERE id > 100 * (1 - 21 * 0.005)
)
SELECT
id, total = CAST( 0.000 AS DECIMAL(10,3))
INTO #temp
FROM
"data"
OPTION ( MAXRECURSION 23 );
UPDATE t SET #total = total = #total + id FROM #temp t
SELECT * FROM #temp
See SQL-Fiddle for testing.