views:

164

answers:

4

I have a number of type Decimal(8, 2) and have been using Substring to get fractional value.

E.g.)
 declare @val decimal(8, 2), @strVal varchar(10)
 set @val = 15.80
 set @strVal = cast(@val as varchar)
 select @val, substring(@strVal, charindex('.', @strVal), len(@strVal))

Is there a better way to simply get fractional value, .80 from @val without having to convert it to a character?
I am wondering if there is a built-in UDF (User-Defined Function) that would parse instead of having to rolling out my own version.

+1  A: 

I think you mean the fractional value, not the decimal value. You already have teh decimal value. To get the fractional value, use Round, or Floor functions

  Declare @Fraction Decimal(8,2)
  Set @Fraction = @Val - Floor(@Val)

or

  Set @Fraction = @Val - Round(@Val, 0)
Charles Bretana
I haven't explored *mathematical* functions, yet and this looks like a simply but yet reliable way to get a fractional number. Thanks Charles.
Sung Meister
No problem, check out the Round, and the floor reference links, to see how they work and the diofferences between them...
Charles Bretana
+1  A: 
SET @val = (@val - ROUND(@val, 0, 1) * 100)

The ROUND(@val, 0, 1) should truncate the 15.80 into a 15.00. Then you subtract the 15 from the 15.80, and multiply the 0.80 by 100 to get 80 in numeric form.

The ROUND function requires the third parameter set to 1 to truncate the number. Otherwise, it would convert 15.80 into 16.00. See: http://msdn.microsoft.com/en-us/library/ms175003.aspx.

Daniel Vassallo
+4  A: 

Use the modulus (%) operator. You'll get 0.80.

Like this:

declare @val decimal(8, 2)
set     @val = 15.80
select  @val, @val % 1
md5sum
Elegant solution. I just tried this and it worked.
Greg
Ha, expected nothing less from a guy with a handle, `md5sum`. Thanks.
Sung Meister
It works for negative numbers just fine!
Sung Meister
Not sure why people continuously overlook the modulus operator... I've seen some REALLY bizarre ways of stripping whole numbers off of decimal values.
md5sum
Prolly cause you keep spamming SO with this same thread ?
JonH
A: 
declare @val decimal(8, 2), @strVal varchar(10)  
declare @theint int

set @val = 15.80
SELECT @theint = @val

PRINT @val     --prints 15.80
PRINT @theint  --prints 15

print @val-@theint  --prints .80

print @val % @theint  --prints .80
JonH
Why the extra `SELECT` s? i.e.: `set @val = (SELECT 15.80)` and `SELECT @theint = (SELECT @val)` could be rewritten: `SET @val = 15.80` and `SET @theint = @val` . While the method works, it's actually more work. The select costs more in execution.
md5sum
Could be either way. The execution is not different at all.
JonH
The execution difference is pretty vast... check your execution plan. Although the relative TIME difference is very small, if you do this a lot, you'll see some performance loss.`SET @val = (SELECT 15.80)` raises query cost from 17% to 52% over `SET @val = 15.80` because of the "Compute Scalar" and "Constant Scan" operations.`SELECT @theint = (SELECT @val)` raises query cost to 48% from 17% over `SET @theint = @val` because of the "Constant Scan" operation.All other parts of the query get dropped to < 1% of the effective cost of the query with the added work. All would be 17% otherwise.
md5sum
Absolutely not, they both produce the same plans. Stop pulling BS outta yer hat. Both are acceptable and the only difference is more typing. Also set is used to set once, while select is used for multiple. Please stop bsing.
JonH
They do NOT produce the same execution plan in MSSQL 2008 as tagged by the author of the question. However, I cannot vouch for previous versions. I'd be more than happy to produce screenshots of the execution plans for you.
md5sum
Yes they do SELECT @test = val OR SELECT @test = (SELECT val) both the same, difference is typing. Stop being an idiot.
JonH
Namecalling aside, there appears to be a difference (as tested using SSMS on 2008), in that the version with the additional select (`SELECT @theint = (SELECT @val)`) produces an execution plan with a single "Constant Scan" element, whereas the version without it (`SELECT @theint = @val`) produces no execution plan at all.
Adam Robinson
@Adam I think you guys are missing the point.The originator asked a question, BOTH solutions are the same its just less typing. If it makes a difference then use SELECT @x=myVar rather then SELECT @x = (SELECT myVar). To each his own but making this a huge topic is plain stupid.
JonH