give me your suggestion

  • I have a task like number(digits) to word format

    example 1900 =thousand and nine hundred

    if i using this type it takes very lengthy coding..

    what i do

    My attempt like this..

    create PROCEDURE NUMTOWORD

    @INPUT AS BIGINT

    AS

    BEGIN

    IF(LEN(@INPUT) = 1)

    SELECT CASE @INPUT

    WHEN 1 THEN 'ONE'

    WHEN 2 THEN 'TWO'

    WHEN 3 THEN 'THREE'

    WHEN 4 THEN 'FOUR'

    WHEN 5 THEN 'FIVE'

    WHEN 6 THEN 'SIX'

    WHEN 7 THEN 'SEVEN'

    WHEN 8 THEN 'EIGHT'

    WHEN 9 THEN 'NINE'

    WHEN 0 THEN 'ZERO'

    ELSE '**' END

    ELSE IF(LEN(@INPUT) = 2)

    PRINT 'EXCEED'

    END

    GO

  • First, you should be warned that string manipulations like this should be done by the application, not in SQL. The reasons for this are to protect the SQL Server from the calculation load and to minimize the data being transported over the network. That said, if you MUST do it in SQL, the following code is an example of how it can be done.

    If this is going to be a regular occurrence in your system, I would suggest using the above code to create a permanent table consisting of two columns. The first column would be a primary key consisting only of the integers for the range where you might use this. The second column would contain the full text of the number in words. You can then easily join to this table whenever you have to do the conversion. I suspect it will also run much faster, but I can't test that until later today. When I have a chance I will post up the code and the results.

    Please let me know if you have any questions.

    declare @sample int

    set @sample = 1919

    declare @numwords table(number int, ones varchar(15), tens varchar(15), hundreds varchar(15), thousands varchar(15))

    insert into @numwords

    select 0,'','','','' union all

    select 1,'One','Ten','One Hundred','One Thousand' union all

    select 2,'Two','Twenty','Two Hundred','Two Thousand' union all

    select 3,'Three','Thirty','Three Hundred','Three Thousand' union all

    select 4,'Four','Forty','Four Hundred','Four Thousand' union all

    select 5,'Five','Fifty','Five Hundred','Five Thousand' union all

    select 6,'Six','Sixty','Six Hundred','Six Thousand' union all

    select 7,'Seven','Seventy','Seven Hundred','Seven Thousand' union all

    select 8,'Eight','Eighty','Eight Hundred','Eight Thousand' union all

    select 9,'Nine','Ninety','Nine Hundred','NineThousand' union all

    select 10,'Nineteen','','','' union all

    select 11,'Eleven','','','' union all

    select 12,'Twelve','','','' union all

    select 13,'Thirteen','','','' union all

    select 14,'Fourteen','','','' union all

    select 15,'Fifteen','','','' union all

    select 16,'Sixteen','','','' union all

    select 17,'Seventeen','','','' union all

    select 18,'Eighteen','','','' union all

    select 19,'Nineteen','','',''

    select max(case when number = substring(reverse(@sample),4,1) then thousands else '' end)

    ,max(case when number = substring(reverse(@sample),3,1) then hundreds else '' end)

    ,max(case when right(@sample,2) not between 11 and 19 and number = substring(reverse(@sample),2,1) then tens else '' end)

    ,max(case when right(@sample,2) not between 11 and 19 and number = right(@sample,1) then ones

    when right(@sample,2) between 11 and 19 and number = right(@sample,2) then ones

    else '' end)

    ,max(right(@sample,2))/*and number = substring(reverse(@sample),2,1) <> 1 then ones

    when substring(reverse(@sample),2,1) = 1 and number = right(@sample,2) then ones

    else '' end) */

    from @Numwords

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • Once the table is built it appears to be more efficient to just look a number up. Running the test below with 9999 different numbers, the join to the existing table takes about 200 ms elapsed time and the version which builds the string on the fly runs in over 1300 ms. The difference in CPU time is MUCH greater. However, there may be much faster ways to build the string than the solution I threw together. If I find one that runs faster than simply looking the string up by means of a join to a prepopulated table, I will post it here.

    declare @numwords table(number int, ones varchar(15), tens varchar(15), hundreds varchar(15), thousands varchar(15))

    insert into @numwords

    select 0,NULL,NULL,NULL,NULL union all

    select 1,'One','Ten','One Hundred','One Thousand' union all

    select 2,'Two','Twenty','Two Hundred','Two Thousand' union all

    select 3,'Three','Thirty','Three Hundred','Three Thousand' union all

    select 4,'Four','Forty','Four Hundred','Four Thousand' union all

    select 5,'Five','Fifty','Five Hundred','Five Thousand' union all

    select 6,'Six','Sixty','Six Hundred','Six Thousand' union all

    select 7,'Seven','Seventy','Seven Hundred','Seven Thousand' union all

    select 8,'Eight','Eighty','Eight Hundred','Eight Thousand' union all

    select 9,'Nine','Ninety','Nine Hundred','NineThousand' union all

    select 10,'Nineteen',NULL,NULL,NULL union all

    select 11,'Eleven',NULL,NULL,NULL union all

    select 12,'Twelve',NULL,NULL,NULL union all

    select 13,'Thirteen',NULL,NULL,NULL union all

    select 14,'Fourteen',NULL,NULL,NULL union all

    select 15,'Fifteen',NULL,NULL,NULL union all

    select 16,'Sixteen',NULL,NULL,NULL union all

    select 17,'Seventeen',NULL,NULL,NULL union all

    select 18,'Eighteen',NULL,NULL,NULL union all

    select 19,'Nineteen',NULL,NULL,NULL

    set statistics time on;

    with expanded as

    (select N

    ,max(case when number = substring(reverse(N),4,1) then thousands else '' end) as thousands

    ,max(case when number = substring(reverse(N),3,1) then hundreds else '' end) as hundreds

    ,max(case when right(N,2) not between 11 and 19 and number = substring(reverse(N),2,1) then tens else '' end) as tens

    ,max(case when right(N,2) not between 11 and 19 and number = right(N,1) then ones

    when right(N,2) between 11 and 19 and number = right(N,2) then ones

    else '' end) as ones

    from @Numwords

    cross join dbo.Tally

    group by N

    )

    select N,isnull(thousands+' ','')+isnull(hundreds+' ','')+isnull(tens+' ','')+isnull(ones,'')

    from expanded

    where N <= 9999

    set statistics time off;

    -- create a temp table to test lookup

    create table #numwords (number int primary key, words varchar(200))

    ;with expanded as

    (select N

    ,max(case when number = substring(reverse(N),4,1) then thousands else '' end) as thousands

    ,max(case when number = substring(reverse(N),3,1) then hundreds else '' end) as hundreds

    ,max(case when right(N,2) not between 11 and 19 and number = substring(reverse(N),2,1) then tens else '' end) as tens

    ,max(case when right(N,2) not between 11 and 19 and number = right(N,1) then ones

    when right(N,2) between 11 and 19 and number = right(N,2) then ones

    else '' end) as ones

    from @Numwords

    cross join dbo.Tally

    group by N

    )

    insert into #numwords

    select N,isnull(thousands+' ','')+isnull(hundreds+' ','')+isnull(tens+' ','')+isnull(ones,'')

    from expanded

    where N <= 9999

    --select * from #numwords

    set statistics time on;

    -- test using join to existing table

    select t.N,nw.words

    from dbo.tally t

    join #numwords nw on t.N = nw.Number

    set statistics time off;

    -- test join with set of 9999 random numbers

    create table #testSet (testnum int)

    insert into #testset

    select ABS(CHECKSUM(NEWID())) % 9998 + 1

    from dbo.tally

    where N < 10000

    set statistics time on;

    -- test using join to existing table

    select t.testnum,nw.words

    from #testSet t

    join #numwords nw on t.testNum = nw.Number

    set statistics time off;

    drop table #numwords

    drop table #testSet

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • In addition to Bob Hovious code you might want to read this article by Anthony Zarkin

    which includes all the necessary code to create user functions to convert numbers

    to words and queries to test the results.

    http://www.sqlservercentral.com/scripts/function/65640/

    I the case of your example the return would be:

    One Thousand Nine Hundred

    If everything seems to be going well, you have obviously overlooked something.

    Ron

    Please help us, help you -before posting a question please read[/url]
    Before posting a performance problem please read[/url]

  • I just tested the function from that article ... it is SLOW!!!!

    9999 rows converted using that function takes almost 20 seconds!!!

    set statistics time on;

    -- test using join to existing table

    select t.testnum,nw.words

    from #testSet t

    join #numwords nw on t.testNum = nw.Number

    set statistics time off;

    (9999 row(s) affected)

    SQL Server Execution Times:

    CPU time = 32 ms, elapsed time = 235 ms.

    set statistics time on;

    -- test using the user function from the article

    select testnum,dbo.fnSpellInteger(testNum)

    from #testSet

    set statistics time off;

    (9999 row(s) affected)

    SQL Server Execution Times:

    CPU time = 19218 ms, elapsed time = 19916 ms.

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • Bob Hovious (3/5/2009)


    I just tested the function from that article ... it is SLOW!!!!

    9999 rows converted using that function takes almost 20 seconds!!!

    Heh... I absolutely love it... let me officially welcome you to the "Doubting Thomas Club for SQL". Our motto is "Make it work, make it fast, make it pretty... and it ain't done 'til it's pretty!" Well done!

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Thanks Jeff... I take more pride in a compliment like that from you than I would from an MVP.... although unfortunately it doesn't look as good on a resume. πŸ˜‰

    You know of course that I'm still going to come gunning for you occasionallly like some punk gunslinger out to make a rep. :w00t:

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • Bob, How does it compares with Steve's Solution ?


    * Noel

  • Steve posted his times for 11000 rows as follows

    SQL Server Execution Times:

    CPU time = 4992 ms, elapsed time = 5213 ms.

    When I tested it on my box at 9999 rows to get apples to apples, the results were still not good.

    set statistics time on;

    -- test using join to existing table

    select t.testnum,nw.words

    from #testSet t

    join #numwords nw on t.testNum = nw.Number

    set statistics time off;

    (9999 row(s) affected)

    SQL Server Execution Times:

    CPU time = 31 ms, elapsed time = 230 ms.

    set statistics time on;

    -- test using Steve's user function from the discussion of the article

    select testnum,dbo.fnSpellIntegerSteve(testNum)

    from #testSet

    set statistics time off;

    (9999 row(s) affected)

    SQL Server Execution Times:

    CPU time = 16938 ms, elapsed time = 17873 ms.

    SQL is just really, REALLY good at looking stuff up.

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • Jeff Moden (3/5/2009)


    Bob Hovious (3/5/2009)


    I just tested the function from that article ... it is SLOW!!!!

    9999 rows converted using that function takes almost 20 seconds!!!

    Heh... I absolutely love it... let me officially welcome you to the "Doubting Thomas Club for SQL". Our motto is "Make it work, make it fast, make it pretty... and it ain't done 'til it's pretty!" Well done!

    Hey Jeff Unless my beer is speaking for me, there was a very similar exercise a few months ago...I'm gonna look, if only 'cos it was so much fun then! πŸ™‚

    β€œWrite the query the simplest way. If through testing it becomes clear that the performance is inadequate, consider alternative query forms.” - Gail Shaw

    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

  • Bob Hovious (3/5/2009)


    Thanks Jeff... I take more pride in a compliment like that from you than I would from an MVP.... although unfortunately it doesn't look as good on a resume. πŸ˜‰

    You know of course that I'm still going to come gunning for you occasionallly like some punk gunslinger out to make a rep. :w00t:

    Heh... You DID get the compliment from an MVP.... I got the MVP award last July... I just don't brag about it and they wanted a bit too much information than I was comfortable with on the MVP website.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Chris Morris (3/5/2009)


    Jeff Moden (3/5/2009)


    Bob Hovious (3/5/2009)


    I just tested the function from that article ... it is SLOW!!!!

    9999 rows converted using that function takes almost 20 seconds!!!

    Heh... I absolutely love it... let me officially welcome you to the "Doubting Thomas Club for SQL". Our motto is "Make it work, make it fast, make it pretty... and it ain't done 'til it's pretty!" Well done!

    Hey Jeff Unless my beer is speaking for me, there was a very similar exercise a few months ago...I'm gonna look, if only 'cos it was so much fun then! πŸ™‚

    If it looks like you're seeing double or triple when you find them, don't worry... it's not the beer. There have been many such exercises in the last couple of months... some I participated in, some not. πŸ™‚

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • You DID get the compliment from an MVP

    I heard you were an MVP. What I meant to say was that I took more pride in that compliment than in BEING an MVP. From what I heard recently, starting a blog and making some posts on the right forums would get me in like Flynn, whether or not the posts were up to SSC standards. :hehe:

    __________________________________________________

    Against stupidity the gods themselves contend in vain. -- Friedrich Schiller
    Stop, children, what's that sound? Everybody look what's going down. -- Stephen Stills

  • Bob Hovious (3/5/2009)


    You DID get the compliment from an MVP

    I heard you were an MVP. What I meant to say was that I took more pride in that compliment than in BEING an MVP. From what I heard recently, starting a blog and making some posts on the right forums would get me in like Flynn, whether or not the posts were up to SSC standards. :hehe:

    BWAA-HAA!!! That would be true in many cases... all part of the reason I haven't finished my online registration for it... I'm not too happy with many of the folks that get/have the MVP and the incidents you're talking about are proof of that.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

Viewing 15 posts - 1 through 15 (of 18 total)

You must be logged in to reply to this topic. Login to reply