November 26, 2008 at 4:12 pm
My guess would be that it is the SUBSTRING()'s in your ON clauses.
[font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
Proactive Performance Solutions, Inc. [/font][font="Verdana"] "Performance is our middle name."[/font]
November 26, 2008 at 9:06 pm
Chris Morris (11/26/2008)
Chris, the link in your signature is broken. You'r missing the right hand bracket on the first instance of the URL IFCode ShortCut.
--Jeff Moden
Change is inevitable... Change for the better is not.
November 27, 2008 at 12:51 am
rbarryyoung (11/26/2008)
My guess would be that it is the SUBSTRING()'s in your ON clauses.
You're spot on. It works fine in 2k, I should have tested it in 2k5 :blush:. The problem is with the first join (hundreds):
LEFT JOIN @tblNum h ON number < 15 AND SUBSTRING(@numberstr, number-2, 1) BETWEEN h.Num AND h.MaxNum
In 2k5, the substring is evaluated even when number = 15, which returns the decimal point from the substring expression.
So here's a 2k5-friendly version:
[font="Courier New"]ALTER FUNCTION dbo.ToWords(@TheNumber DECIMAL (15,2), @CurrencyName VARCHAR(20), @JoinWord VARCHAR(20), @CentsName VARCHAR(20))
RETURNS VARCHAR(200)
-- USAGE: SELECT dbo.ToWords(1.01, 'dollar(s)', 'and', 'cent(s)')
-- MAX. VALUE: 999999999999.99 (twelve nines before the decimal point)
BEGIN
DECLARE @numberstr CHAR (15), @NewString VARCHAR(200)
SET @numberstr = STR(@TheNumber, 15, 2)
SET @NewString = ''
DECLARE @tblNum TABLE(Num BIGint, MaxNum BIGint, NumStr VARCHAR(20))
INSERT INTO @tblNum
SELECT 1, 1, 'one' UNION ALL SELECT 2, 2, 'two' UNION ALL
SELECT 3, 3, 'three' UNION ALL SELECT 4, 4, 'four' UNION ALL
SELECT 5, 5, 'five' UNION ALL SELECT 6, 6, 'six' UNION ALL
SELECT 7, 7, 'seven' UNION ALL SELECT 8, 8, 'eight' UNION ALL
SELECT 9, 9, 'nine' UNION ALL SELECT 10, 10, 'ten' UNION ALL
SELECT 11, 11, 'eleven' UNION ALL SELECT 12, 12, 'twelve' UNION ALL
SELECT 13, 13, 'thirteen' UNION ALL SELECT 14, 14, 'fourteen' UNION ALL
SELECT 15, 15, 'fifteen' UNION ALL SELECT 16, 16, 'sixteen' UNION ALL
SELECT 17, 17, 'seventeen' UNION ALL SELECT 18, 18, 'eighteen' UNION ALL
SELECT 19, 19, 'nineteen' UNION ALL SELECT 20, 29, 'twenty' UNION ALL
SELECT 30, 39, 'thirty' UNION ALL SELECT 40, 49, 'forty' UNION ALL
SELECT 50, 59, 'fifty' UNION ALL SELECT 60, 69, 'sixty' UNION ALL
SELECT 70, 79, 'seventy' UNION ALL SELECT 80, 89, 'eighty' UNION ALL
SELECT 90, 99, 'ninety' UNION ALL SELECT 100, 999, 'hundred' UNION ALL
SELECT 1000, 999999, 'thousand' UNION ALL SELECT 1000000, 999999999, 'million' UNION ALL
SELECT 1000000000, 999999999999, 'billion'
SELECT @NewString = @NewString
+ CASE WHEN h.NumStr IS NULL THEN '' ELSE h.NumStr + ' ' + c.NumStr + ' ' END
+ CASE WHEN number < 15 AND h.NumStr IS NOT NULL AND (t.NumStr IS NOT NULL OR u.NumStr IS NOT NULL) THEN @JoinWord + ' ' ELSE '' END
+ CASE WHEN number < 15 AND t.NumStr IS NOT NULL THEN t.NumStr + ' ' ELSE '' END
+ CASE WHEN number < 15 AND u.NumStr IS NOT NULL THEN u.NumStr + ' ' ELSE '' END
+ CASE WHEN number = 12 THEN @CurrencyName + ' ' ELSE '' END
+ CASE WHEN number = 15 AND (t.NumStr IS NOT NULL OR u.NumStr IS NOT NULL) THEN @JoinWord + ' ' ELSE '' END
+ CASE WHEN number = 15 AND t.NumStr IS NOT NULL THEN t.NumStr + ' ' ELSE '' END
+ CASE WHEN number = 15 AND u.NumStr IS NOT NULL THEN u.NumStr + ' ' ELSE '' END
+ CASE WHEN number = 15 AND (t.NumStr IS NOT NULL OR u.NumStr IS NOT NULL) THEN @CentsName + ' ' ELSE '' END
+ CASE WHEN k.NumStr IS NULL THEN '' ELSE k.NumStr + ', ' END
FROM (SELECT 3 AS number UNION ALL SELECT 6 UNION ALL SELECT 9 UNION ALL SELECT 12 UNION ALL SELECT 15) n
LEFT JOIN @tblNum h ON number < 15 AND REPLACE(SUBSTRING(@numberstr, number-2, 1), '.', '') BETWEEN h.Num AND h.MaxNum
LEFT JOIN @tblNum t ON SUBSTRING(@numberstr, number-1, 2) BETWEEN t.Num AND t.MaxNum AND t.Num > 9
LEFT JOIN @tblNum u ON SUBSTRING(@numberstr, number, 1) BETWEEN u.Num AND u.MaxNum AND NOT SUBSTRING(@numberstr, number-1, 2) BETWEEN 10 AND 19
LEFT JOIN @tblNum c ON number < 15 AND c.Num = 100
LEFT JOIN @tblNum k ON number < 12 AND k.Num = POWER(10, 12-number) AND k.Num < @TheNumber
RETURN @NewString
END
GO
--SELECT dbo.ToWords(number, 'dollar(s)', 'and', 'cent(s)')
--FROM Numbers
--WHERE number < 30000
-- about a minute
SELECT dbo.ToWords(999999999999.99, 'dollar(s)', 'and', 'cent(s)')
-- nine hundred and ninety nine billion, nine hundred and ninety nine million,
-- nine hundred and ninety nine thousand, nine hundred and ninety nine dollar(s) and ninety nine cent(s)
SELECT dbo.ToWords(999999999999.99, 'pounds', 'and', 'pence')
-- nine hundred and ninety nine billion, nine hundred and ninety nine million,
-- nine hundred and ninety nine thousand, nine hundred and ninety nine pounds and ninety nine pence
[/font]
Cheers
ChrisM
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
November 27, 2008 at 2:28 am
Jeff Moden (11/26/2008)
Chris Morris (11/26/2008)
Chris, the link in your signature is broken. You'r missing the right hand bracket on the first instance of the URL IFCode ShortCut.
Thanks Jeff, it's fixed now. Dunno if it's restrictions on the work pc's here but the sig editor has a mind of it's own.
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
November 27, 2008 at 9:46 am
Chris Morris (11/27/2008)Dunno if it's restrictions on the work pc's here but the sig editor has a mind of it's own.
I hear that. It took me forever to get my signature right. :crazy:
[font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
Proactive Performance Solutions, Inc. [/font][font="Verdana"] "Performance is our middle name."[/font]
November 27, 2008 at 10:40 am
Here's a 2k/2k5-friendly version with a permanent lookup table. It translates 30,000 numbers from a standard tally table, in both SQL Server versions, in about 4 seconds.
[font="Courier New"]IF EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N'[dbo].[NumbersAsWords]') AND OBJECTPROPERTY(id, N'IsUserTable') = 1)
DROP TABLE [dbo].[NumbersAsWords]
CREATE TABLE [dbo].[NumbersAsWords] (
[Num] [bigint] NULL ,
[MaxNum] [bigint] NULL ,
[NumStr] [varchar] (20) COLLATE Latin1_General_CI_AS NULL
) ON [PRIMARY]
CREATE CLUSTERED INDEX [Num] ON [dbo].[NumbersAsWords]([Num]) ON [PRIMARY]
CREATE INDEX [MaxNum] ON [dbo].[NumbersAsWords]([MaxNum]) ON [PRIMARY]
INSERT INTO dbo.NumbersAsWords
SELECT 1, 1, 'one' UNION ALL SELECT 2, 2, 'two' UNION ALL
SELECT 3, 3, 'three' UNION ALL SELECT 4, 4, 'four' UNION ALL
SELECT 5, 5, 'five' UNION ALL SELECT 6, 6, 'six' UNION ALL
SELECT 7, 7, 'seven' UNION ALL SELECT 8, 8, 'eight' UNION ALL
SELECT 9, 9, 'nine' UNION ALL SELECT 10, 10, 'ten' UNION ALL
SELECT 11, 11, 'eleven' UNION ALL SELECT 12, 12, 'twelve' UNION ALL
SELECT 13, 13, 'thirteen' UNION ALL SELECT 14, 14, 'fourteen' UNION ALL
SELECT 15, 15, 'fifteen' UNION ALL SELECT 16, 16, 'sixteen' UNION ALL
SELECT 17, 17, 'seventeen' UNION ALL SELECT 18, 18, 'eighteen' UNION ALL
SELECT 19, 19, 'nineteen' UNION ALL SELECT 20, 29, 'twenty' UNION ALL
SELECT 30, 39, 'thirty' UNION ALL SELECT 40, 49, 'forty' UNION ALL
SELECT 50, 59, 'fifty' UNION ALL SELECT 60, 69, 'sixty' UNION ALL
SELECT 70, 79, 'seventy' UNION ALL SELECT 80, 89, 'eighty' UNION ALL
SELECT 90, 99, 'ninety' UNION ALL SELECT 100, 999, 'hundred' UNION ALL
SELECT 1000, 999999, 'thousand' UNION ALL SELECT 1000000, 999999999, 'million' UNION ALL
SELECT 1000000000, 999999999999, 'billion'
---------------------------------------------------------------------------------------------------
GO
ALTER FUNCTION [dbo].[ToWords](
@TheNumber DECIMAL (15,2),
@CurrencyName VARCHAR(20),
@JoinWord VARCHAR(20),
@CentsName VARCHAR(20))
RETURNS VARCHAR(200)
-- USAGE: SELECT dbo.ToWords(1.01, 'dollar(s)', 'and', 'cent(s)')
-- MAX. VALUE: 999999999999.99 (twelve nines before the decimal point)
BEGIN
DECLARE @numberstr CHAR (15), @NewString VARCHAR(200)
SET @numberstr = STR(@TheNumber, 15, 2)
SET @NewString = ''
SELECT @NewString = @NewString
+ ISNULL(h.NumStr + ' ' + c.NumStr + ' ', '')
+ CASE WHEN (number = 15 OR h.NumStr IS NOT NULL) AND COALESCE(t.NumStr, u.NumStr) IS NOT NULL THEN @JoinWord + ' ' ELSE '' END
+ ISNULL(t.NumStr + ' ', '')
+ ISNULL(u.NumStr + ' ', '')
+ CASE WHEN number = 12 THEN @CurrencyName + ' ' ELSE '' END
+ CASE WHEN number = 15 AND COALESCE(t.NumStr, u.NumStr) IS NOT NULL THEN @CentsName ELSE '' END
+ CASE WHEN COALESCE(h.NumStr, t.NumStr, u.NumStr) IS NOT NULL THEN ISNULL(k.NumStr + ', ', '') ELSE '' END
FROM (SELECT 3 AS number UNION ALL SELECT 6 UNION ALL SELECT 9 UNION ALL SELECT 12 UNION ALL SELECT 15) n
LEFT JOIN NumbersAsWords h ON number < 15 AND REPLACE(SUBSTRING(@numberstr, number-2, 1), '.', '') BETWEEN h.Num AND h.MaxNum
LEFT JOIN NumbersAsWords t ON SUBSTRING(@numberstr, number-1, 2) BETWEEN t.Num AND t.MaxNum AND t.Num > 9
LEFT JOIN NumbersAsWords u ON SUBSTRING(@numberstr, number, 1) BETWEEN u.Num AND u.MaxNum AND NOT SUBSTRING(@numberstr, number-1, 2) BETWEEN 10 AND 19
LEFT JOIN NumbersAsWords c ON number < 15 AND c.Num = 100
LEFT JOIN NumbersAsWords k ON number < 12 AND k.Num = POWER(10, 12-number) AND k.Num <= @TheNumber
WHERE number > 15-LEN(@TheNumber)
RETURN @NewString
END
GO
SELECT dbo.ToWords(number, 'dollar(s)', 'and', 'cent(s)')
FROM Numbers
WHERE number < 30000
-- about four seconds
SELECT dbo.ToWords(number, 'dollar(s)', 'and', 'cent(s)')
FROM Numbers
WHERE number BETWEEN 970001 AND 1000000
-- about five seconds
SELECT dbo.ToWords(100.01, 'dollar(s)', 'and', 'cent(s)')
-- one hundred dollar(s) and one cent(s)
SELECT dbo.ToWords(999999999999.99, 'dollar(s)', 'and', 'cent(s)')
-- nine hundred and ninety nine billion, nine hhundred and ninety nine million,
-- nine hundred and ninety nine thousand, nine hundred and ninety nine dollar(s)
-- and ninety nine cent(s)
SELECT dbo.ToWords(999999999999.99, 'pounds', 'and', 'pence')
-- nine hundred aand ninety nine billion, nine hundred and ninety nine million,
-- nine hundred and ninety nine thousand, nine hundred and ninety nine pounds
-- and ninety nine pence
[/font]
Many thanks for the help guys, I learn something every time I come here.
Cheers
ChrisM
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
November 27, 2008 at 11:08 am
Man, you write nice code, Chris. I always enjoy reading it.
[font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
Proactive Performance Solutions, Inc. [/font][font="Verdana"] "Performance is our middle name."[/font]
November 27, 2008 at 11:35 am
Chris Morris (11/27/2008)
Here's a 2k/2k5-friendly version with a permanent lookup table. It translates 30,000 numbers from a standard tally table, in both SQL Server versions, in about 4 seconds.
Ummm... try this and see if that time sticks... π it's still 30,000 rows
SELECT dbo.ToWords(number, 'dollar(s)', 'and', 'cent(s)')
FROM Numbers
WHERE number BETWEEN 970001 AND 1000000
--Jeff Moden
Change is inevitable... Change for the better is not.
November 27, 2008 at 12:43 pm
Jeff Moden (11/27/2008)
Chris Morris (11/27/2008)
Here's a 2k/2k5-friendly version with a permanent lookup table. It translates 30,000 numbers from a standard tally table, in both SQL Server versions, in about 4 seconds.Ummm... try this and see if that time sticks... π it's still 30,000 rows
SELECT dbo.ToWords(number, 'dollar(s)', 'and', 'cent(s)')
FROM Numbers
WHERE number BETWEEN 970001 AND 1000000
The timing's very similar Jeff, but many many thanks for this, it did point out some 'areas for improvement'.
RBarryYoung (11/27/2008)
Man, you write nice code, Chris. I always enjoy reading it.
:blush: erm, :blush: so long as it looks nice! Sometimes it works too...
Cheers
ChrisM
For fast, accurate and documented assistance in answering your questions, please read this article.
Understanding and using APPLY, (I) and (II) Paul White
Hidden RBAR: Triangular Joins / The "Numbers" or "Tally" Table: What it is and how it replaces a loop Jeff Moden
November 27, 2008 at 1:21 pm
Chris Morris (11/27/2008)
RBarryYoung (11/27/2008)
Man, you write nice code, Chris. I always enjoy reading it.:blush: erm, :blush: so long as it looks nice! Sometimes it works too...
I mean the logic and the style, not just the formatting.
[font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
Proactive Performance Solutions, Inc. [/font][font="Verdana"] "Performance is our middle name."[/font]
November 27, 2008 at 3:04 pm
Chris Morris (11/27/2008)
Jeff Moden (11/27/2008)
Chris Morris (11/27/2008)
Here's a 2k/2k5-friendly version with a permanent lookup table. It translates 30,000 numbers from a standard tally table, in both SQL Server versions, in about 4 seconds.Ummm... try this and see if that time sticks... π it's still 30,000 rows
SELECT dbo.ToWords(number, 'dollar(s)', 'and', 'cent(s)')
FROM Numbers
WHERE number BETWEEN 970001 AND 1000000
The timing's very similar Jeff, but many many thanks for this, it did point out some 'areas for improvement'.
I asked only because my machine is a bit old (but I still love it!) and any timing differences are pretty well magnified. The 30k example you posted took 11 seconds on my humble desktop instead of just 4 seconds. The 30k example I asked you to run jumped up to 13 seconds.
You say "some 'areas for improvement'"... what did you improve?
--Jeff Moden
Change is inevitable... Change for the better is not.
November 27, 2008 at 4:37 pm
Very cool code, Chris... your' guy's efforts made me finish up what I started and it looks nothing like the original code I posted... I couldn't stand the fact that I was using Correlated Subqueries and that is was pretty slow.
First, like everyone else, we need a reference table with words for things. I took a radically different approach than everyone else did on this one. Heh... it's kind of a "Rosetta Stone" for how to name integers except... note the absence of the number "Zero"...
--===== Create the table that that is used to form the words
-- This only need be executed once, ever.
CREATE TABLE dbo.NumberWord
(
Unit INT,
UnitWord VARCHAR(5),
TeenWord VARCHAR(9),
TenWord VARCHAR(7),
ThousandWord VARCHAR(11),
CONSTRAINT PK_NumberWord_Unit
PRIMARY KEY CLUSTERED (UNIT) WITH FILLFACTOR = 100
)
INSERT INTO NumberWord
(Unit,UnitWord,TeenWord ,TenWord ,ThousandWord)
SELECT 1 ,'One' ,'Eleven' ,'Ten' ,'Thousand' UNION ALL
SELECT 2 ,'Two' ,'Twelve' ,'Twenty' ,'Million' UNION ALL
SELECT 3 ,'Three' ,'Thirteen' ,'Thirty' ,'Billion' UNION ALL
SELECT 4 ,'Four' ,'Fourteen' ,'Fourty' ,'Trillion' UNION ALL
SELECT 5 ,'Five' ,'Fifteen' ,'Fifty' ,'Quadrillion' UNION ALL
SELECT 6 ,'Six' ,'Sixteen' ,'Sixty' ,'Quintillion' UNION ALL
SELECT 7 ,'Seven' ,'Seventeen','Seventy','Sextillion' UNION ALL
SELECT 8 ,'Eight' ,'Eighteen' ,'Eighty' ,'Septillion' UNION ALL
SELECT 9 ,'Nine' ,'Nineteen' ,'Ninety' ,'Octillian'
GO
As with many other solutions, the Tally table figures prominately as a character splitter. If you don't already have one, now's the time to make this very useful tool. See the following (linked) article for that and more...
[font="Arial Black"]The "Numbers" or "Tally" Table: What it is and how it replaces a loop.[/font][/url]
Here's the code I wrote for the function... similar to Chris' but different because of the reference table I used...
CREATE FUNCTION dbo.NumberToWords
/**************************************************************************************************
Purpose:
Convert a 0 to 2 decimal place number, including negative numbers, to words like you may find
for the written out amount on a check. "Optional extra" words may be added. See the "Input
Parameters" section of the code below for more details.
Notes:
1. All parameters must be present but may be Blank (empty string) or Null
Revision History:
Rev 00 - 27 Nov 2008 - Jeff Moden - Initial creation for the folks at SQLServerCentral.com.
References: Original request:
http://www.sqlservercentral.com/Forums/Topic584374-360-1.aspx
Tally table info:
http://www.sqlservercentral.com/articles/TSQL/62867/
**************************************************************************************************/
(--==== Input parameters
@SomeNumber DECIMAL (32,2), -- +- 30 digits + up to 2 decimal places
@IntegerType VARCHAR(32), -- Example: 'Dollar(s)' on checks or NULL or Blank
@DecimalPlace VARCHAR(32), -- Example: 'And' on checks or NULL or Blank
@DecimalType VARCHAR(32) -- Example: 'Cent(s)' or '/100 Dollar(s)' on checks.
-- Can also be NULL or Blank
)
RETURNS VARCHAR(8000)
AS
BEGIN -------------------------------------------------------------------------------------------
--===== Declare local variables
DECLARE @Result VARCHAR(8000), --Holds most of what we want to return
@NumberString CHAR(33) --The number converted to a right justified string
--===== Convert the number to a postive number and right justify it so we know where things are at.
SELECT @NumberString = RIGHT(REPLICATE(' ',33) + CAST(ABS(@SomeNumber) AS VARCHAR(33)),33)
--===== Find and concatenate all the words we need for the positive integer part of the number
SELECT @Result = COALESCE(@Result + ',' ,'')
+ ISNULL(' ' + hundred.UnitWord + ' Hundred','')
+ CASE WHEN split.Teen BETWEEN 11 AND 19 THEN '' ELSE ISNULL(' ' + ten.TenWord,'') END
+ CASE WHEN split.Teen BETWEEN 11 AND 19 THEN '' ELSE ISNULL(' ' + one.UnitWord,'') END
+ CASE WHEN split.Teen BETWEEN 11 AND 19 THEN ISNULL(' ' + teen.TeenWord,'') ELSE '' END
+ ISNULL(' ' + thousand.ThousandWord,'')
FROM (--==== Split the number into component parts based on "triplets" of digits in the number.
-- This is nothing more than a split using a Tally table in steps of 3 characters
-- as controlled by Modulo 3.
SELECT (28-N)/3 AS Thousand,
NULLIF(SUBSTRING(@NumberString,N,3),0) AS Triplet,
SUBSTRING(@NumberString,N,1) AS Hundred,
SUBSTRING(@NumberString,N+1,1) AS Ten,
SUBSTRING(@NumberString,N+2,1) AS One,
SUBSTRING(@NumberString,N+1,2) AS Teen
FROM dbo.Tally
WHERE N <= 30
AND N%3 = 1)split
LEFT JOIN dbo.NumberWord AS hundred ON split.Hundred = hundred.Unit
LEFT JOIN dbo.NumberWord AS ten ON split.Ten = ten.Unit
LEFT JOIN dbo.NumberWord AS one ON split.One = one.Unit
LEFT JOIN dbo.NumberWord AS teen ON RIGHT(split.Teen,1) = teen.Unit
LEFT JOIN dbo.NumberWord AS thousand ON split.Thousand = thousand.Unit
WHERE split.Triplet IS NOT NULL
--===== Add the other markers and parts to display and exit.
RETURN CASE WHEN @SomeNumber < 0 THEN 'Minus ' ELSE '' END
+ ISNULL(LTRIM(@Result),'Zero')
+ ISNULL(' ' + @IntegerType ,'')
+ ISNULL(' ' + @DecimalPlace ,'')
+ ' ' + RIGHT(@NumberString,2)
+ ISNULL(' ' + @DecimalType ,'')
END -------------------------------------------------------------------------------------------
And, here's some tests I ran that also explain some usage possibilities... the "-15000.xx" is just so we can see what happens for negative numbers and when is crosses "Zero"
SELECT dbo.NumberToWords (t.N-15000,'Dollar(s)','And','Cent(s)')
FROM dbo.Tally t
WHERE t.N BETWEEN 1 AND 30000
SELECT dbo.NumberToWords (t.N-15000.03,NULL,'And','/100 Dollar(s)')
FROM dbo.Tally t
WHERE t.N BETWEEN 1 AND 30000
Chris, would you do me the honor of running my code on your box a couple of times? I just wanna make sure I haven't lost my touch because your code ran damned fast. π
Oh yeah... I almost forgot the disclaimer to make everyone happy... here goes...
"This should really be done in the GUI... if you have one." :hehe:
Heh... speaking of "gew", anyone care to write a CLR for this and comparitively test for performance? I don't care much for CLR's, but this seems like it might be a good place to do this type of nasty conversion.
--Jeff Moden
Change is inevitable... Change for the better is not.
November 27, 2008 at 4:39 pm
Jeff Moden (11/27/2008)
I asked only because my machine is a bit old (but I still love it!) and any timing differences are pretty well magnified. The 30k example you posted took 11 seconds on my humble desktop instead of just 4 seconds. The 30k example I asked you to run jumped up to 13 seconds.
Well, the total string length of your example is about 10-20% larger than Chris's original, so that makes sense, doesn't it?
[font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
Proactive Performance Solutions, Inc. [/font][font="Verdana"] "Performance is our middle name."[/font]
November 27, 2008 at 4:47 pm
For the most part, Yes. On concatenation of such a small number of parts, not really.
--Jeff Moden
Change is inevitable... Change for the better is not.
November 27, 2008 at 5:07 pm
Jeff:
Your function is called "NumberToWords" but you are calling "MoneyToWords", is this just a typo or am I missing something?
[font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
Proactive Performance Solutions, Inc. [/font][font="Verdana"] "Performance is our middle name."[/font]
Viewing 15 posts - 16 through 30 (of 46 total)
You must be logged in to reply to this topic. Login to reply