Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Avg() to return a decimal? 2

Status
Not open for further replies.

HestonJames

Programmer
Aug 11, 2008
187
GB
Hello Guys,

This will be a simple enough question I'm sure, I suspect its caused by datatype mismatches of some kind between int's and float's or something, maybe you can help?

I have a simple query which looks like this:

Code:
Select	Max(message_count.messagecount) As Highest,
		Min(message_count.messagecount) As Lowest,
		Avg(message_count.messagecount) As Average
From (
	Select		MessageLog.Device_ID,
				Count(Distinct MessageLog.Media_ID) AS MessageCount
	From		MessageLog
	Group By	MessageLog.Device_ID
	) As message_count

This query runs without error however, the AVG() returned seems to be rounded down, rather than a proper decimal placed average of the column values that I really want.

So for instance, example result sets might look like this:

Highest: 2
Lowest: 1
Average: 1

or

Highest: 4
Lowest: 1
Average: 1

Now, am I using Avg() correctly here? or should I be using another method?

At the moment I'm able to solve the issue by doing something like this: Where I cast the value as a float instead of what I'm guessing is an Int.

Code:
Select	Max(message_count.messagecount) As Highest,
		Min(message_count.messagecount) As Lowest,
		Avg([COLOR=#ff0000]cast(message_count.messagecount as float)[/color]) As Average
From (
	Select		MessageLog.Device_ID,
				Count(Distinct MessageLog.Media_ID) AS MessageCount
	From		MessageLog
	Group By	MessageLog.Device_ID
	) As message_count

I'm just interested to see if this is the correct way of handling it, or is there is a better built in method to be using?

Cheers all,

Heston
 
Hey r937,

Thanks for that, I'm guessing that multiplying by the float forces the cast to happen automagicaly? is that correct?

Cheers,

Heston
 
Yes.

In my opinion, it's "no better/no worse" than your solution.

In your code, you did an explicit conversion to float. Rudy's code causes an explicit data type conversion. Personally, I prefer the explicit method (cast/convert). For me, it's more obvious (when you read the code) what is actually happening. You could also argue that the implicit method (multiply by 1.0) is less code. Less code isn't necessarily important, but it allows you to more easily focus on the other important aspects of the code. In this case, it's important to realize that you are getting an average. It's less important that you need to convert to float in order to get an accurate average.

It's worth knowing the order in which SQL Server does it's implicit (auto-magical) conversions. Take a look here.

user-defined data types (highest)
1. sql_variant
2. xml
3. datetime
4. smalldatetime
5. float
6. real
7. decimal
8. money
9. smallmoney
10. bigint
11. int
12. smallint
13. tinyint
14. bit
15. ntext
16. text
17. image
18. timestamp
19. uniqueidentifier
20. nvarchar (including nvarchar(max) )
21. nchar
22. varchar (including varchar(max) )
23. char
24. varbinary (including varbinary(max) )
25. binary (lowest)

Not all data types can be converted to other data types, but when then can, and SQL Server needs to do this for you auto-magically, this list is what it uses to determine the resulting data type.

For example... 1.0 * 20

1.0 is float
20 is int

According to the list, float is #5, int is #11. When combining these data types, SQL Server will convert to float because it has a higher precedent on the list.

Make sense?

-George

"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
George,

That is very interesting! I've added a copy of that datatype list to my notepad here to keep it in mind.

It's nice to know there isn't any real benefit to either I or r937's approach apart from personal preference.

Cheers to you both for this, very helpful!

Heston
 
Rudy,

You're right.

Code:
Select SQL_VARIANT_PROPERTY([!]1.0[/!], 'BaseType') As [Base Type], 
       SQL_VARIANT_PROPERTY([!]1.0[/!], 'Precision') As [Precision], 
       SQL_VARIANT_PROPERTY([!]1.0[/!], 'Scale') As [Scale]

Output:
[tt]
Base Type Precision Scale
--------- --------- -----
numeric 2 1
[/tt]

-George

"The great things about standards is that there are so many to choose from." - Fortune Cookie Wisdom
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top