Author Message J Livingston SQL One Orange Chip Group: General Forum Members Points: 27420 Visits: 41392 another method here:http://sqlbump.blogspot.co.uk/2010/06/sum-of-digits-of-number.html ________________________________________________________________you can lead a user to data....but you cannot make them think and remember....every day is a school day SomewhereSomehow SSC Eights! Group: General Forum Members Points: 856 Visits: 469 Cool!!! 4 ways to solve the problem! Definitly all go to my KB.CELKO's - is the fastest or isn't it? Who will make a proof test?psCELKO,Are you a Joe Celko, the one, who was the author of marvellous chapter in Itzik Ben Gan book? (Sorry for tactless question). I am really sorry for my poor gramma. And I hope that value of my answers will outweigh the harm for your eyes.Blog: http://somewheresomehow.ruTwitter: @SomewereSomehow J Livingston SQL One Orange Chip Group: General Forum Members Points: 27420 Visits: 41392 SomewhereSomehow (8/5/2012)...Who will make a proof test?go on...give it a crack:-) ________________________________________________________________you can lead a user to data....but you cannot make them think and remember....every day is a school day SQL Padawan Old Hand Group: General Forum Members Points: 366 Visits: 1172 I could be wrong but Celko's method is the fastest. One thing to keep in mind is the LEN function's limit is 8000 characters or in other words the sum of all digits can not exceed 8000... Mark Cowne SSChampion Group: General Forum Members Points: 14864 Visits: 26582 Million row test for three of the solutions. Results are interesting/surpising. Perhaps some of you folks could check this and run it.`--===== Conditionally drop the test table to make reruns in SSMS easier. -- This is NOT a part of the solution. IF OBJECT_ID('tempdb..#Test','U') IS NOT NULL DROP TABLE #Test;--===== Create and populate the test table. -- This is NOT a part of the solution. SELECT TOP (1000000) TestID = IDENTITY(INT,1,1), TestNumber = ABS(CHECKSUM(NEWID())) INTO #Test FROM sys.all_columns ac1 CROSS JOIN sys.all_columns ac2;--===== Add the expected PK ALTER TABLE #Test ADD PRIMARY KEY CLUSTERED (TestID);-----------------------------------------------------------------------------PRINT '========== SomewhereSomehow ==========================================='SET STATISTICS TIME ON;DECLARE @T INT;with nums(n) as(select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10))nums(n))select @T = sum(convert(int,substring(convert(varchar(10),TestNumber),n,1)))from numsCROSS JOIN #Testwhere n <= len(convert(varchar(10),TestNumber))GROUP BY TestNumber;SET STATISTICS TIME OFF;GOPRINT '========== CELKO ==========================================='SET STATISTICS TIME ON;DECLARE @T INTSELECT @T = LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (TestNumber AS VARCHAR(150)) ,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'))FROM #Test;SET STATISTICS TIME OFF;GOPRINT '========== Mark ====================================================='SET STATISTICS TIME ON;DECLARE @T INT;WITH Tens(Pos,Val) AS (SELECT 1, 1 UNION ALLSELECT 2, 10 UNION ALLSELECT 3, 100 UNION ALLSELECT 4, 1000 UNION ALLSELECT 5, 10000 UNION ALLSELECT 6, 100000 UNION ALLSELECT 7, 1000000 UNION ALLSELECT 8, 10000000 UNION ALLSELECT 9, 100000000 UNION ALLSELECT 10,1000000000)SELECT @T = SUM((TestNumber / Val) % 10)FROM TensCROSS JOIN #TestWHERE Val<=TestNumberGROUP BY TestNumber;SET STATISTICS TIME OFF;` ____________________________________________________Deja View - The strange feeling that somewhere, sometime you've optimised this query beforeHow to get the best help on a forumhttp://www.sqlservercentral.com/articles/Best+Practices/61537 Cadavre SSC-Insane Group: General Forum Members Points: 22196 Visits: 8519 Mark-101232 (8/6/2012)Million row test for three of the solutions. Results are interesting/surpising. Perhaps some of you folks could check this and run it.Celko forgot to account for the REPLACE "bug".Change his code to this: -`DECLARE @T INT = 985;SELECT LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (@T AS VARCHAR(150)) COLLATE Latin1_General_BIN2,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'));`Then take another look at your test results: -`--===== Conditionally drop the test table to make reruns in SSMS easier. -- This is NOT a part of the solution. IF OBJECT_ID('tempdb..#Test','U') IS NOT NULL DROP TABLE #Test;--===== Create and populate the test table. -- This is NOT a part of the solution. SELECT TOP (1000000) TestID = IDENTITY(INT,1,1), TestNumber = ABS(CHECKSUM(NEWID())) INTO #Test FROM sys.all_columns ac1 CROSS JOIN sys.all_columns ac2;--===== Add the expected PK ALTER TABLE #Test ADD PRIMARY KEY CLUSTERED (TestID);-----------------------------------------------------------------------------PRINT '========== SomewhereSomehow ==========================================='SET STATISTICS TIME ON;DECLARE @T INT;with nums(n) as(select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10))nums(n))select @T = sum(convert(int,substring(convert(varchar(10),TestNumber),n,1)))from numsCROSS JOIN #Testwhere n <= len(convert(varchar(10),TestNumber))GROUP BY TestNumber;SET STATISTICS TIME OFF;GOPRINT '========== CELKO ==========================================='SET STATISTICS TIME ON;DECLARE @T INTSELECT @T = LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (TestNumber AS VARCHAR(150)) ,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'))FROM #Test;SET STATISTICS TIME OFF;GOPRINT '========== Mark ====================================================='SET STATISTICS TIME ON;DECLARE @T INT;WITH Tens(Pos,Val) AS (SELECT 1, 1 UNION ALLSELECT 2, 10 UNION ALLSELECT 3, 100 UNION ALLSELECT 4, 1000 UNION ALLSELECT 5, 10000 UNION ALLSELECT 6, 100000 UNION ALLSELECT 7, 1000000 UNION ALLSELECT 8, 10000000 UNION ALLSELECT 9, 100000000 UNION ALLSELECT 10,1000000000)SELECT @T = SUM((TestNumber / Val) % 10)FROM TensCROSS JOIN #TestWHERE Val<=TestNumberGROUP BY TestNumber;SET STATISTICS TIME OFF;GOPRINT '========== IMPROVED CELKO ==========================================='SET STATISTICS TIME ON;DECLARE @T INT;SELECT @T = LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (TestNumber AS VARCHAR(150)) COLLATE Latin1_General_BIN2,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'))FROM #Test;SET STATISTICS TIME OFF;GO``========== SomewhereSomehow =========================================== SQL Server Execution Times: CPU time = 28155 ms, elapsed time = 8756 ms.========== CELKO =========================================== SQL Server Execution Times: CPU time = 24343 ms, elapsed time = 24385 ms.========== Mark ===================================================== SQL Server Execution Times: CPU time = 19921 ms, elapsed time = 6877 ms.========== IMPROVED CELKO =========================================== SQL Server Execution Times: CPU time = 3594 ms, elapsed time = 3619 ms.`--edit--Found the link to the replace "bug" Forever trying to learnFor better, quicker answers on T-SQL questions, click on the following...http://www.sqlservercentral.com/articles/Best+Practices/61537/For better, quicker answers on SQL Server performance related questions, click on the following...http://www.sqlservercentral.com/articles/SQLServerCentral/66909/If you litter your database queries with nolock query hints, are you aware of the side effects?Try reading a few of these links...(*) Missing rows with nolock(*) Allocation order scans with nolock(*) Consistency issues with nolock(*) Transient Corruption Errors in SQL Server error log caused by nolock(*) Dirty reads, read errors, reading rows twice and missing rows with nolockCraig Wilkinson - Software EngineerLinkedIn Mark Cowne SSChampion Group: General Forum Members Points: 14864 Visits: 26582 Cadavre (8/6/2012)Mark-101232 (8/6/2012)Million row test for three of the solutions. Results are interesting/surpising. Perhaps some of you folks could check this and run it.Celko forgot to account for the REPLACE "bug".Change his code to this: -`DECLARE @T INT = 985;SELECT LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (@T AS VARCHAR(150)) COLLATE Latin1_General_BIN2,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'));`Then take another look at your test results: -`--===== Conditionally drop the test table to make reruns in SSMS easier. -- This is NOT a part of the solution. IF OBJECT_ID('tempdb..#Test','U') IS NOT NULL DROP TABLE #Test;--===== Create and populate the test table. -- This is NOT a part of the solution. SELECT TOP (1000000) TestID = IDENTITY(INT,1,1), TestNumber = ABS(CHECKSUM(NEWID())) INTO #Test FROM sys.all_columns ac1 CROSS JOIN sys.all_columns ac2;--===== Add the expected PK ALTER TABLE #Test ADD PRIMARY KEY CLUSTERED (TestID);-----------------------------------------------------------------------------PRINT '========== SomewhereSomehow ==========================================='SET STATISTICS TIME ON;DECLARE @T INT;with nums(n) as(select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10))nums(n))select @T = sum(convert(int,substring(convert(varchar(10),TestNumber),n,1)))from numsCROSS JOIN #Testwhere n <= len(convert(varchar(10),TestNumber))GROUP BY TestNumber;SET STATISTICS TIME OFF;GOPRINT '========== CELKO ==========================================='SET STATISTICS TIME ON;DECLARE @T INTSELECT @T = LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (TestNumber AS VARCHAR(150)) ,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'))FROM #Test;SET STATISTICS TIME OFF;GOPRINT '========== Mark ====================================================='SET STATISTICS TIME ON;DECLARE @T INT;WITH Tens(Pos,Val) AS (SELECT 1, 1 UNION ALLSELECT 2, 10 UNION ALLSELECT 3, 100 UNION ALLSELECT 4, 1000 UNION ALLSELECT 5, 10000 UNION ALLSELECT 6, 100000 UNION ALLSELECT 7, 1000000 UNION ALLSELECT 8, 10000000 UNION ALLSELECT 9, 100000000 UNION ALLSELECT 10,1000000000)SELECT @T = SUM((TestNumber / Val) % 10)FROM TensCROSS JOIN #TestWHERE Val<=TestNumberGROUP BY TestNumber;SET STATISTICS TIME OFF;GOPRINT '========== IMPROVED CELKO ==========================================='SET STATISTICS TIME ON;DECLARE @T INT;SELECT @T = LEN ( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE( REPLACE(REPLACE(REPLACE(REPLACE(REPLACE (CAST (TestNumber AS VARCHAR(150)) COLLATE Latin1_General_BIN2,'0', '') ,'1', '#') ,'2', '##') ,'3', '###') ,'4', '####') ,'5', '#####') ,'6', '######') ,'7', '#######') ,'8', '########') ,'9', '#########'))FROM #Test;SET STATISTICS TIME OFF;GO``========== SomewhereSomehow =========================================== SQL Server Execution Times: CPU time = 28155 ms, elapsed time = 8756 ms.========== CELKO =========================================== SQL Server Execution Times: CPU time = 24343 ms, elapsed time = 24385 ms.========== Mark ===================================================== SQL Server Execution Times: CPU time = 19921 ms, elapsed time = 6877 ms.========== IMPROVED CELKO =========================================== SQL Server Execution Times: CPU time = 3594 ms, elapsed time = 3619 ms.`--edit--Found the link to the replace "bug"That explains a lot, thanks!Also the CELKO solution can be improved a bit by removing the REPLACE(...,'1', '#') - the code is simply counting characters so there's no point changing 1's to #'s. ____________________________________________________Deja View - The strange feeling that somewhere, sometime you've optimised this query beforeHow to get the best help on a forumhttp://www.sqlservercentral.com/articles/Best+Practices/61537 Sumit Rastogi Old Hand Group: General Forum Members Points: 389 Visits: 159 declare @string varchar(max) = '25475675675675675675675675675587876865674553334645647656786867879789780890890789676565674545634343453445675756756786867897978978078997896785657454563445345234534645675678768997807867567456342323167567567567567567567567567567567567567567567665756756756756756756756756756756756756756767876879789797287686782567345345289789797278978978978979245645622222245645622222222435645645645646364564564564564564564564564564564564564564564564562'declare @s varchar(1)declare @totalcount int = 0declare @count intset @count = LEN(@string)while (@count != 0)begin set @count = @count - 1 set @s=convert(int,left(@string, 1)) set @string = RIGHT(@string, len(@string)-1) set @totalcount = @totalcount + @send print convert(varchar,@totalcount)Thanks,Sumit Rastogi SomewhereSomehow SSC Eights! Group: General Forum Members Points: 856 Visits: 469 Cadavre,Thx for the testing scripts! Especially pointing a bug with replace function (closed as by design).I have quite similar results`========== SomewhereSomehow =========================================== SQL Server Execution Times: CPU time = 19813 ms, elapsed time = 5501 ms. ========== CELKO =========================================== SQL Server Execution Times: CPU time = 20437 ms, elapsed time = 20529 ms. ========== Mark ===================================================== SQL Server Execution Times: CPU time = 12891 ms, elapsed time = 3846 ms. ========== IMPROVED CELKO =========================================== SQL Server Execution Times: CPU time = 2859 ms, elapsed time = 2853 ms.` I am really sorry for my poor gramma. And I hope that value of my answers will outweigh the harm for your eyes.Blog: http://somewheresomehow.ruTwitter: @SomewereSomehow