SQL Server floating point numbers - sql

I was wondering if there is a way to show the values of columns of type floating point numbers in two decimal places in SQL Server 2008 via settings? For instance, let say I have a table called orders with several columns. I want to be able to do the following:
SELECT * FROM orders
I expect to see any values in columns of type float to display with decimal notation; for instance, a value of 4 should display as 4.0 or 4.00.
Thanks

You may use CONVERT function with NUMERIC( x , 2) for numeric values
( where x is at least 3, better more, upto 38 )
SELECT CONVERT(NUMERIC(10, 2), 4 ) as "Dcm Nr(2)";
Dcm Nr(2)
---------
4,00
SELECT CONVERT(NUMERIC(10, 1), 4 ) as "Dcm Nr(1)";
Dcm Nr(1)
---------
4,0

The simplest form of what happens to me is making a "cast", for example:
SELECT CAST(orders AS DECIMAL(10,2)) FROM [your table];

The short answer to your question is "No".
SQL Server isn't really in the business of data presentation. We all do a lot of backbends from time to time to force things into a presentable state, and the other answers provided so far can help you on a column by column basis.
But the sort of "set it and forget it" thing you're looking for is better handled in a front end application.

Related

How to query column with letters on SQL?

I'm new to this.
I have a column: (chocolate_weight) On the table : (Chocolate) which has g at the end of every number, so 30x , 2x5g,10g etc.
I want to remove the letter at the end and then query it to show any that weigh greater than 35.
So far I have done
Select *
From Chocolate
Where chocolate_weight IN
(SELECT
REPLACE(chocolote_weight,'x','') From Chocolate) > 35
It is coming back with 0 , even though there are many that weigh more than 35.
Any help is appreciated
Thanks
If 'g' is always the suffix then your current query is along the right lines, but you don't need the IN you can do the replace in the where clause:
SELECT *
FROM Chocolate
WHERE CAST(REPLACE(chocolate_weight,'g','') AS DECIMAL(10, 2)) > 35;
N.B. This works in both the tagged DBMS SQL-Server and MySQL
This will fail (although only silently in MySQL) if you have anything that contains units other than grams though, so what I would strongly suggest is that you fix your design if it is not too late, store the weight as an numeric type and lose the 'g' completely if you only ever store in grams. If you use multiple different units then you may wish to standardise this so all are as grams, or alternatively store the two things in separate columns, one as a decimal/int for the numeric value and a separate column for the weight, e.g.
Weight
Unit
10
g
150
g
1000
lb
The issue you will have here though is that you will have start doing conversions in your queries to ensure you get all results. It is easier to do the conversion once when the data is saved and use a standard measure for all records.

Round function query 2 to 3 arguments?

I am attempting to find the revenue per distinct user in this query but seem to be running in this error.
select concat('$',format(cast(round(sum(total)/count(distinct(customers))),2)
as int),N'N','en-US')
from table
My error:
The round function requires 2 to 3 arguments
I suspect you mean:
SELECT CONCAT('$',FORMAT(CAST(ROUND(SUM(Total)/COUNT(DISTINCT customers),2) AS int),N'N'),'en-US')
FROM [table];
But, really, worry about the formatting of your values in your presentation layer (The FORMAT and CONCAT don't need to be there).
Also, Why ROUND({expr},2) and then CAST({expr} AS int)? Why not ROUND({expr},0)?
For instance used 2 as length to round
round(sum(total)/count(distinct(customers)),2)

Redshift numeric precision truncating

I have encountered situation that I can't explain how Redshift handles division of SUMs.
There is example table:
create table public.datatype_test(
a numeric(19,6),
b numeric(19,6));
insert into public.datatype_test values(222222.2222, 333333.3333);
insert into public.datatype_test values(444444.4444, 666666.6666);
Now I try to run query:
select sum(a)/sum(b) from public.datatype_test;
I get result 0.6666 (4 decimals). It is not related to tool display, it really returns only 4 decimal places, and it doesn't matter how big or small numbers are in table. In my case 4 decimals is not precise enough.
Same stands true if I use AVG instead of SUM.
If I use MAX instead of SUM, I get : 0.6666666666666666666 (19 decimals).
It also returns correct result (0.6666666666666667) when no phisical table is used:
with t as (
select 222222.2222::numeric(19,6) as a, 333333.3333::numeric(19,6) as b union all
select 444444.4444::numeric(19,6) as a, 666666.6666::numeric(19,6) as b
)
select sum(a)/sum(b) as d from t;
I have looked into Redshift documentation about SUM and Computations with Numeric Values, but I still don't get result according to documentation.
Using float datatype for table columns is not an option as I need to store precise currency amounts and 15 significant digits is not enough.
Using cast on SUM aggregation also gives 0.6666666666666666666 (19 decimals).
select sum(a)::numeric(19,6)/sum(b) from public.datatype_test;
But it looks wrong, and I can't force BI tools to do this workaround, also everyone who uses this data should not use this kind of workaround.
I have tried to use same test in PostgreSQL 10, and it works as it should, returning sufficient amount of decimals for division.
Is there anything I can do with database setup to avoid casting in SQL Query?
Any advice or guidance is highly appreciated.
Redshift version:
PostgreSQL 8.0.2 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 3.4.2 20041017 (Red Hat 3.4.2-6.fc3), Redshift 1.0.4081
Using dc2.8xlarge nodes
I have run into similar issues, and although I don't have a solution that doesn't require a workaround, I can at least explain it.
The precision/scale of the result of division is defined by the rules in the "computations with numeric values" document.
A consequence of those rules is that a decimal(19,6) divided by another decimal(19,6) will return decimal(38,19).
What's happening to you, though, is that MAX returns the same precision/scale as the underlying column, but SUM returns decimal(38,*) no matter what.
(This is probably a safety precaution to prevent overflow on sums of "big data"). If you divide decimal(38,6) by another, you get decimal(38,4).
AWS support will probably not consider this a defect -- there is no SQL standard for how to treat decimal precision in division, and given that this is documented behavior, it's probably a deliberate decision.
The only way to address this is to typecast the numerator, or multiply it by something like sum(a) * cast(1 as decimal(10,9)) which is portable SQL and will force more decimal places in the numerator and thus the result.
As a convenience I made a calculator in JSFiddle with the rules so you can play around with different options:
scale = Math.max(4, s1 + p2 - s2 + 1)
precision = p1 - s1 + s2 + scale
if (precision > 38) {
scale = Math.max((38 + scale - precision), 4)
precision = 38
}

How to capture data values to the power of ^ (...) in SQL Server?

Perhaps someone with more experience in SQL Server can be of assistance. I am in the middle of putting together the LookUp tables for a new project. For 2 different tests that a user can perform (Bacteria/Fungi) the results are currently recorded on paper as the following:
BACTERIA:
Bacteria cfu / ml
<100
10^2
10^3
10^4
10^5
10^6
10^7
FUNGI:
Fungi (yeast & mold) cfu /ml
<100
10^2
10^3
10^4
10^5
What would be the best way to capture these values in SQL Server 2008 R2? In particular, Data Type and Size?
Something like this would probably be good enough:
CREATE TABLE AmountLookup (
UnitsLimitExp int NULL,
Name nvarchar(10) NULL
)
INSERT INTO AmountLookup
SELECT 2, '<100'
UNION ALL SELECT 3, '10^3'
UNION ALL SELECT 4, '10^4'
UNION ALL SELECT 5, '10^5'
UNION ALL SELECT 6, '10^6'
UNION ALL SELECT 7, '10^7'
This way you store the exponent, not the amount. Real value is just a GUI representation. Another thing is your lookup name, which is ugly here (10^3). However, you can store HTML code and treat it as raw HTML on your user interface, e.g. 104 is 10<sup>4</sup>.
If these are value and not ranges, INT will work. If you start to deal with values greater than 2 billion, BIGINT should be used. If you need decimal digits, you can use the DECIMAL (NUMERIC) type.
Your other option, since these are discrete values, is to use a lookup table for the values, whose surrogate key id you can use in the tables that hold references to the data. That way you can represent a concept such as "<100" .
I'd propose a varchar(50):
<100 "Clean enough"
10^2 "Food over due date"
10^3 "Mr Bean's armpits"
10^4 "Three day old carcass"
10^5 "Biochemical experiment"
10^6 "Maggot invasion"
10^7 "Bacteria overflow"

How to average values based on location proximity

I have an SQL table with geo-tagged values (Longitude, Latitude, value). The table is accumulated quickly and has thousands entries. Therefore, querying the table for values in some area return very large data-set.
I would like to know the way to average value with close location proximity to one value, here is an illustration:
Table:
Long lat value
10.123001 53.567001 10
10.123002 53.567002 12
10.123003 53.567003 18
10.124003 53.568003 13
lets say my current location is 10.123004, 53.567004. If I am querying for the values near by I will get the four raws with values 10, 12, 18, and 13. This works if the data-set is relatively small. If the data is large I would like to query sql for rounded location (10.123, 53.567) and need sql to return something like
Long lat value
10.123 53.567 10 (this is the average of 10, 12, and 18)
10.124 53.568 13
Is this possible? how we can average large data set based on locations?
Is sql database is the right choice in the first place?
GROUP BY rounded columns, and the AVG aggregate function should work fine for this:
SELECT ROUND(Long, 3) Long,
ROUND(Lat, 3) Lat,
AVG(value)
FROM Table
GROUP BY ROUND(Long, 3), ROUND(Lat, 3)
Add a WHERE clause to filter as needed.
Here's some rough pseudocode that might be a start. You need to provide the proper precision arguments for the round function in the dialect of SQL you are using for your project, so understand that the 3 I provide as the second argument to Round is the number of decimals of precision to which the number is rounded, as indicated by your original post.
Select round(lat,3),round(long,3),avg(value)
Group by round(lat,3),round(long,3)
The problem with the rounding approach is the boundary conditions -- what happens when points are close to the bounday.
However, for the neighborhood of a given point it is better to use something like:
select *
from table
where long between #MyLong - #DeltaLong and #MyLong + #DeltaLong and
lat between #MyLat - #DeltaLat and #MyLat + #DeltaLat
For this, you need to define #DeltaLong and #DeltaLat.
Rounding works fine for summarization, if that is your problem.