Ok... this takes 2 seconds longer (1,000,000 rows in 23 seconds instead of 21)... had to work around the "zero domain" on the LOG10 function to get this to work properly for whole numbers...
DECLARE @TestNum DECIMAL(38,15) SET @TestNum = 99 --99.0000
SELECT CASE WHEN FLOOR(REVERSE(ABS(@TestNum))) = 0.0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(@TestNum)))+1) END
It does NOT support FLOAT... (the original problem description was based on the DECIMAL datatype so I think we're ok there)... Float does wierd things when you throw a REVERSE on it. If anyone needs a decimal place counter that works on FLOAT, we'll have to take a different tact...
10-PATINDEX('%[^0]%',REVERSE(RIGHT(CAST(mynumber as varchar),9))+'1')
1,000,000 rows <=10 secs
Far away is close at hand in the images of elsewhere.
Anon.
Very cool, David... fast as all get out... but try this... obviously, we have to know exactly what the scale of the decimal places is to use it or we come up with the wrong answer...
DECLARE @TestNum DECIMAL(38,15) SET @TestNum = 99.123456789012345 SELECT 10-PATINDEX('%[^0]%',REVERSE(RIGHT(CAST(@TestNum as varchar),9))+'1')
However... you gave me one heck of an idea... the following takes a bit more time (1,000,000 records in about 12 seconds)...
DECLARE @TestNum DECIMAL(38,15) SET @TestNum = 90 --99.123456780000000 --0.123456780000000 --99.1 --90
SELECT CHARINDEX('.',REVERSE(@TestNum)) -PATINDEX('%[^0]%',REVERSE(@TestNum))
...the neat thing about it is that you don't need to know the precision or scale of the decimal column... it figures it out...
SELECT TestNum, Jeff=CASE WHEN FLOOR(REVERSE(ABS(TestNum))) = 0.0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)))+1) END ,Markus=CASE WHEN FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 < 0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 END ,Dwain=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE LEN(CAST(REVERSE(ABS(TestNum) % 1) AS DECIMAL(38,0))) ENDFROM ( SELECT CAST(99 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.1 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.11 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.1111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.11111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.111111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.1111111111111111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(0.1 AS DECIMAL(38,15))) Nums(TestNum)CREATE TABLE #BigNums (TestNum DECIMAL(38,15))INSERT INTO #BigNumsSELECT 1.* CHECKSUM(NEWID()) / POWER(10, ABS(CHECKSUM(NEWID())) % 10)FROM ( SELECT TOP 1000000 1 FROM sys.all_columns a, sys.all_columns b )Tally(n)DECLARE @Hold DECIMAL(38,15)PRINT 'Jeff'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(REVERSE(ABS(TestNum))) = 0.0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)))+1) ENDFROM #BigNumsSET STATISTICS TIME OFFPRINT 'Markus'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 < 0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 ENDFROM #BigNumsSET STATISTICS TIME OFFPRINT 'Dwain'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE LEN(CAST(REVERSE(ABS(TestNum) % 1) AS DECIMAL(38,0))) ENDFROM #BigNumsSET STATISTICS TIME OFFDROP TABLE #BigNums
Jeff SQL Server Execution Times: CPU time = 3339 ms, elapsed time = 3411 ms.Markus SQL Server Execution Times: CPU time = 4227 ms, elapsed time = 4291 ms.Dwain SQL Server Execution Times: CPU time = 2028 ms, elapsed time = 2036 ms.
SELECT TestNum, Jeff=CASE WHEN FLOOR(REVERSE(ABS(TestNum))) = 0.0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)))+1) END ,Markus=CASE WHEN FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 < 0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 END ,Dwain=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE LEN(CAST(REVERSE(ABS(TestNum) % 1) AS DECIMAL(38,0))) END ,DwainRedux=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE LEN(CAST(REVERSE(TestNum - CAST(FLOOR(TestNum) AS DECIMAL)) AS DECIMAL)) ENDFROM ( SELECT CAST(99 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.1 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.11 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.1111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.11111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.111111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(-99.11111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(-99.111111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(99.1111111111111111 AS DECIMAL(38,15)) UNION ALL SELECT CAST(0.1 AS DECIMAL(38,15))) Nums(TestNum)CREATE TABLE #BigNums (TestNum DECIMAL(38,15))INSERT INTO #BigNumsSELECT 1.* CHECKSUM(NEWID()) / POWER(10, ABS(CHECKSUM(NEWID())) % 10)FROM ( SELECT TOP 1000000 1 FROM sys.all_columns a, sys.all_columns b )Tally(n)DECLARE @Hold DECIMAL(38,15)PRINT 'Jeff'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(REVERSE(ABS(TestNum))) = 0.0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)))+1) ENDFROM #BigNumsSET STATISTICS TIME OFFPRINT 'Markus'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 < 0 THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)+1)))+1 ENDFROM #BigNumsSET STATISTICS TIME OFFPRINT 'Dwain'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE LEN(CAST(REVERSE(ABS(TestNum) % 1) AS DECIMAL(38,0))) ENDFROM #BigNumsSET STATISTICS TIME OFFPRINT 'Dwain Redux'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE LEN(CAST(REVERSE(TestNum - CAST(FLOOR(TestNum) AS DECIMAL)) AS DECIMAL)) ENDFROM #BigNumsSET STATISTICS TIME OFFPRINT 'Jeff - Revised WHEN'SET STATISTICS TIME ON SELECT @Hold=CASE WHEN FLOOR(TestNum) = TestNum THEN 0 ELSE FLOOR(LOG10(REVERSE(ABS(TestNum)))+1) ENDFROM #BigNumsSET STATISTICS TIME OFFDROP TABLE #BigNums
Jeff SQL Server Execution Times: CPU time = 3338 ms, elapsed time = 3408 ms.Markus SQL Server Execution Times: CPU time = 4337 ms, elapsed time = 4369 ms.Dwain SQL Server Execution Times: CPU time = 2012 ms, elapsed time = 2071 ms.Dwain Redux SQL Server Execution Times: CPU time = 1888 ms, elapsed time = 1928 ms.Jeff - Revised WHEN SQL Server Execution Times: CPU time = 2293 ms, elapsed time = 2362 ms.