-
Method 4 : Using xml (without variables)
select [sum_of_digits]=
cast(cast(cast(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(@i ,'0', '0')
,'1', '1')
,'2', '2')
,'3', '3')
,'4', '4')
,'5', '5')
,'6', '6')
,'7', '7')
,'8', '8')
,'9', '9')
as xml).query('sum(/a)') as varchar) as int)
regards
Zbigniew
commented on May 7 2012 2:18AM
|
-
commented on May 7 2012 3:08AM
|
-
Good to know Zibi. Thanks for sharing...
commented on May 7 2012 3:52AM
|
-
Zibi, thanks for the alternate method. But it throws the following error
Msg 245, Level 16, State 1, Line 5
Conversion failed when converting the varchar value '0.0E0' to data type int.
commented on May 7 2012 4:29AM
|
-
Hello, this below is proof of such errors
select [sum_of_digits]=
cast(replace(cast(cast(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(@i ,'0', '0')
,'1', '1')
,'2', '2')
,'3', '3')
,'4', '4')
,'5', '5')
,'6', '6')
,'7', '7')
,'8', '8')
,'9', '9')
as xml).query('sum(/a)') as varchar), '0.0E0', '0') as int)
commented on May 7 2012 4:38AM
|
-
As XML parsing is case sensitive, please find below modified query:
declare @i int, @sql varchar(8000)
set @i=798273
select [sum_of_digits]=
cast(replace(cast(cast(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(@i ,'0', '<A>0</A>')
,'1', '<A>1</A>')
,'2', '<A>2</A>')
,'3', '<A>3</A>')
,'4', '<A>4</A>')
,'5', '<A>5</A>')
,'6', '<A>6</A>')
,'7', '<A>7</A>')
,'8', '<A>8</A>')
,'9', '<A>9</A>')
as xml).query('sum(/A)') as varchar), '0.0E0', '0') as int)
commented on May 7 2012 4:45AM
|
-
Ok. It just seems to be case sensitive. You dont need to replace 0.0E0. This is enough
declare @i int
set @i=798273
select [sum_of_digits]=
cast(cast(cast(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(
replace(@i ,'0', '<A>0</A>')
,'1', '<A>1</A>')
,'2', '<A>2</A>')
,'3', '<A>3</A>')
,'4', '<A>4</A>')
,'5', '<A>5</A>')
,'6', '<A>6</A>')
,'7', '<A>7</A>')
,'8', '<A>8</A>')
,'9', '<A>9</A>')
as xml).query('sum(/A)') as varchar) as int)
commented on May 7 2012 4:50AM
|
-
Here's another way to sum the digits of a 32-bit signed integer.
CREATE FUNCTION SumOfDigits(@N int)
RETURNS int AS BEGIN RETURN
(
SELECT ABS(@N) % 10
+ ABS(@N) / CAST(1E1 AS int) % 10
+ ABS(@N) / CAST(1E2 AS int) % 10
+ ABS(@N) / CAST(1E3 AS int) % 10
+ ABS(@N) / CAST(1E4 AS int) % 10
+ ABS(@N) / CAST(1E5 AS int) % 10
+ ABS(@N) / CAST(1E6 AS int) % 10
+ ABS(@N) / CAST(1E7 AS int) % 10
+ ABS(@N) / CAST(1E8 AS int) % 10
+ ABS(@N) / CAST(1E9 AS int) % 10
)
END
commented on May 7 2012 5:14AM
|
-
commented on May 7 2012 5:52AM
|
-
Hello,
another xml approuch
regards
Zbigniew
declare @i int, @sql varchar(8000)
set @i=798273
select [sum_of_digits]=cast(
cast(
cast(''+cast(@i as varchar)+'' as xml).query(
'for $i in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
return
{fn:substring((/a[1])[1], $i, 1)}
')
.query('xs:int(sum(/a))') as varchar) as int
)
go
commented on May 7 2012 8:26AM
|
-
Zibi, thats interesting one. However take care of case sensitive issue. Here is corrected code
declare @i int, @sql varchar(8000)
set @i=798273
select [sum_of_digits]=cast(
cast(
cast('<A>'+cast(@i as varchar)+'</A>' as xml).query(
'for $i in (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13)
return <A>
{fn:substring((/A[1])[1], $i, 1)}
</A>
')
.query('xs:int(sum(/A))') as varchar) as int
)
go
commented on May 7 2012 8:45AM
|
-
select len(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(@i,
'0',''),'1','a'),'2','aa'),'3','aaa'),'4','aaaa'),'5','aaaaa'),'6','aaaaaa'),'7','aaaaaaa'),'8','aaaaaaaa'),'9','aaaaaaaaa'))
commented on May 7 2012 10:39AM
|
-
commented on May 7 2012 11:10AM
|
-
Hi,
Another approach using LEFT AND RIGHT ,
select SUM( CAST (LEFT(RIGHT(@i,LEN(@i)-(number-1)),1) AS INt))
from master..spt_values
where number between 1 and LEN(@i)
and type='p'
commented on Jul 31 2012 5:14AM
|
-
commented on Jul 31 2012 1:47PM
|
-
Thanks Roji. I have not seen you very active in online forums. Are you busy with your work?
commented on Aug 1 2012 1:48AM
|
-
This is good problem! I have had to do this with weights to compute a check digit, so the position of digit in the string was important. But we do not have to worry about that with just a simple sum. We can just convert each digit into a hash mark. Concatenate them and measure the length. This is pure ANSI/ISO Standard SQL without any XML or other foreign language contamenation.
SET @digitssum =
LEN (
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE
(CAST (@ininteger AS VARCHAR(15)) ,'0', '')
,'1', '#')
,'2', '##')
,'3', '###')
,'4', '####')
,'5', '#####')
,'6', '######')
,'7', '#######')
,'8', '########')
,'9', '#########'));
commented on Aug 2 2012 2:37PM
|
-
Typo: CAST (@in_integer AS VARCHAR(150))
commented on Aug 2 2012 2:43PM
|
-
Thanks Madhi. Trying to be bit more active these days.
I'll also offer couple of solutions.
DECLARE @i INT = 987654321
DECLARE @c VARCHAR(250) = CONVERT(VARCHAR, @i)
SELECT @c = REPLACE(@c,n,REPLICATE('*',n))
FROM (SELECT TOP 10 ROW_NUMBER() OVER(ORDER BY @@SPID) -1 FROM sys.objects) T(n)
SELECT LEN(@c)
go
DECLARE @i INT = 123456789
DECLARE @c INT = 0
SELECT @c = @c + ((@i /n)%10)
FROM (SELECT TOP 10 POWER(10,(ROW_NUMBER()
OVER(ORDER BY @@SPID))-1) FROM sys.objects) T(n)
WHERE n <= @i
SELECT @C
commented on Aug 2 2012 5:56PM
|
-
Thanks. Joe celko. That's interesting. I have seen you using it for simulating INITCAP function
commented on Aug 3 2012 3:07AM
|
|