Sql Server display decimals only if they are bigger than 0? - sql

I have this select: select isnull(Pricea,0)-isnull(Priceb,0) as Differences
The format of the columns is decimal(12,4).
My question is: I could somehow to return decimals only if they are bigger than 0?
It seems to be confusing if the result will be for e.g 4.0000 so I would want to display the decimals only if they are bigger than 0. Is this possible?

When ceiling(Num) = floor(Num), the number is a integer
select case when ceiling(Num) = floor(Num)
then CONVERT(varchar, CAST(Num as decimal))
else CONVERT(varchar, Num)
end

It's just the kind of beeing displayed in MangementStudio for the Datatypes.
For just adapting the display kind you could do something like
Declare #a table (a decimal(12,4),b decimal(12,4))
insert into #a Values(12.45,10.45)
insert into #a Values(12.45,10.4512)
insert into #a Values(12.4512,10.4500)
Select Cast(Case when a-b<>Floor(a-b) then Cast(a-b as float) else a-b end as Varchar(30)) as Diff
from #a

Related

passing a variable as a parameter to varchar() as in cast(column1 as varchar(#variable))

Using SQL Server 2014. As a challenge someone asked me to return 113.05 as 0.05 in a select statement.
I put forth the following:
declare #temp1 table (value1 numeric(5,2))
insert into #temp1 (value1)
values
(113.05);
select value1, cast('.' + right(cast(value1 as varchar(6)), 2) as numeric(3,2))
from #temp1;
which works, but then i thought what if there are multiple rows in value1 and all have different lengths other than 6. How can i pass the length of value1 as a parameter as in cast(value1 as varchar(length of value1)?
i have tried declaring a variable #length and setting it to equal len(value1) and then passing it as varchar(#length) but that won't work. Thank you for your assistance.
I wouldn't do this like that at all. Use math, specifically MODULO.
declare #temp1 table (value1 numeric(5,2))
insert into #temp1 (value1)
values
(113.05)
, (911.123)
, (1.22)
, (.3)
select value1
, UsingMath = value1 % 1
from #temp1;

Converting varchar to int (a strange case?)

I have scoured through all "Varchar to Int" posts but can't seem to find anyone with this issue (although, I am fairly new to SQL so I may be doing something fundamentally wrong):
SELECT *
FROM [TABLE]
WHERE CONVERT(INT,
CASE
WHEN NOT CONVERT(VARCHAR(12), dept_code) LIKE '%[^0-9]%' THEN 8900
END) < 9000;
It's a fairly simple query, where the goal is to filter out all the values in field "dept_code" so that only fully numeric values less than 9000 are kept; varchars and non-numeric values are fine to stay. When running the above I still get the error "Conversion failed when converting the varchar value 'E103' to data type int."
Any help would be appreciated.
You can simply this query by avoiding CASE and Regex like expression. You can use IsNumeric function to filter numeric rows and then apply the condition by converting dept_code of filtered rows to int, like below -
select * from tablex
where ISNUMERIC(dept_code) = 0 --alphanumeric code
OR(ISNUMERIC(dept_code) = 1 and Convert(int, dept_code) < 9000) -- numeric less than 9000
Example here
Use try_convert() or try_cast():
SELECT t.*
FROM [TABLE] t
WHERE TRY_CONVERT(int, dept_code) < 9000
If you want to speed this query, you can materialize a computed column and add an index:
alter table [table] add dept_code_int as (try_convert(int, dept_code)) persisted;
create index idx_table_dept_code_int on [table](dept_code_int);
You are missing an else in your case statement ... Secondly do your numeric dept_codes get to be really big ... this thing will choke on that.
SELECT *
FROM [TABLE]
WHERE CONVERT(INT,
CASE
WHEN NOT CONVERT(VARCHAR(12), dept_code) LIKE '%[^0-9]%' THEN 8900 ELSE dept_code
END) < 9000;
Try this: http://sqlfiddle.com/#!18/bb6b7/17
;WITH TABLE_ENHANCED AS
(
SELECT
t.*
, dept_code_numeric =
CASE
WHEN CONVERT(VARCHAR(12), dept_code) NOT LIKE '%[^0-9]%'
THEN CONVERT(INT, dept_code)
ELSE 0
END
FROM [TABLE] t
)
SELECT
*
FROM TABLE_ENHANCED
WHERE dept_code_numeric < 9000
Try below Script
SELECT *
FROM [TABLE]
WHERE isnumeric(dept_code)=1
and dept_code<9000;
This should work. The conversion to int is implicit.
SELECT *
FROM test
WHERE (ISNUMERIC(dept_code)=1 and dept_code<9000)
or (ISNUMERIC(dept_code) = 0)

Select numbers with more than 4 decimal places

I have a SQL table with one float column populated with values like these:
1.4313
3.35
2.55467
6.22456
3.325
I need to select rows containing only values with more than 4 decimals. In this case, the select must return:
2.55467
6.22456
Ideas? Thanks!
This is what I have tried so far
select *
from table
where CAST(LATITUDE AS DECIMAL(10,5)) - LATITUDE = 0
DECLARE #tbl TABLE (val float)
INSERT INTO #tbl SELECT 1234.567
INSERT INTO #tbl SELECT 1234.5678
INSERT INTO #tbl SELECT -1234.5678
INSERT INTO #tbl SELECT 1234.56789
SELECT *
from #tbl
where (((val*10000) - CONVERT(INT,(val*10000))) <> 0)
Why cant we make it simple by this query:-
SELECT * FROM table WHERE val LIKE '%.____%'
This selects what we want
Another solution also:
SELECT * from table
where (round(value,2) - round(value,4) <> 0)
Given answers did not work for me with MaxDb, but this did:
where FLOOR(value * 10000) != value * 10000
Source
Reduce/Increase 0`s for less/more precision.
This works on Postgres 11:
SELECT * FROM mytable WHERE mycolumn != ROUND(mycolumn::numeric,2)
http://sqlfiddle.com/#!3/abadc/3/0
Seems like something like this should work...
all it does is convert the number to an integer to drop off decimals after multiplying it * 10 to power of decimals you need then it compares that int version of the number to the base number after it too was multiplied by 10 to the power of # of decimals.
If the numbers don't match, then you have decimals beyond 4. If they do match, then it was 4 or fewer.
Select *
from foo
where cast(myNum*power(10,4) as int) <> myNum*power(10,4)
Please try something like:
select * from table
where RIGHT(CAST(value as DECIMAL(10,5)), value), 1) != 0
SELECT *
FROM table WHERE
(abs(val)*100000)%10 <> 0
It's an older question but it checks out.
select val
from table
where ((val * 100) % 1) > 0
Change 100 to your precision.
You can multiply it with 10000 and subtract it from the original number replacing . with ''.
Fiddle
select * from tablename
where replace(numcolumn,'.','') - numcolumn * 10000 > 0
Below is the Code that will check the precision for 4 decimal places:
Replace MyNum, with column you are checking for precision
Replace MyTbl, with the table you are using
Replace 4, with whatever precision you are checking for
Sql:
SELECT MyNum
, LEN(CAST (MyNum AS CHAR))
, -------1. length of decimal number, after conversion to CHAR
CHARINDEX('.', CAST (MyNum AS CHAR))
, ---2.length of numbers after the '.'
LEN(CAST (MyNum AS CHAR)) - CHARINDEX('.', CAST (MyNum AS CHAR)) -----subtracting 1-2, to get the length of numbers after decimal point '.'
FROM MyTbl
WHERE LEN(CAST(MyNum AS CHAR)) - CHARINDEX('.', CAST(MyNum AS CHAR)) > 4; --checking if there are more than 4 numbers after the decimal point '.'
Cast the number as text
Split the text using '.' as separator
Use the 2nd index and apply a length
Filter
--i.e. with postgreSQL.
--1)
select data_numeric, length(arr[2]) as str_length
from (
select data_numeric, regexp_split_to_array(data_numeric::text, '\.') as arr from TABLE
) temp;
--2)
with t1 as (
select data_numeric, regexp_split_to_array(data_numeric::text, '\.') as arr from TABLE
), t2 as (
select data_numeric, arr[2] as decimals, length(arr[2]) as length from t1
)
select * from t2;
Select numbers with more than 2 decimal places:
I had an example, where ((abs(val)*100) and CONVERT(INT,(abs(val)*100)) for value "2.32" in float type column returned two different values.
(abs(2.32)*100) = 232
CONVERT(INT,(abs(2.32)*100)) = 231
That caused wrong select query answers in case for comparing to 0.
I suppose that MSSQL CONVERT() function round numbers in such way that for some float number cases, posted solution would not work.
Here is how I did it for more than 2 decimal places:
DECLARE #tbl TABLE (val float)
INSERT INTO #tbl SELECT 2.32
INSERT INTO #tbl SELECT 1234.54
INSERT INTO #tbl SELECT 1234.545
INSERT INTO #tbl SELECT 1234.5456
INSERT INTO #tbl SELECT 1234.54567
select * from #tbl where abs(val-round((val),2)) > 0.001
You can use the scale function, since postgresql 9.6.
select LATITUDE FROM TABLE where scale(LATITUDE) > 4;
If your data type is float you will get SQL Error [42883]: ERROR: function scale(double precision) does not exist. Below would fix it.
select LATITUDE FROM TABLE where scale(cast(LATITUDE as numeric)) > 4;
This is the simplest solution, Use WITH (NOLOCK) if it's necessary in your case otherwise you can remove it. This will return the records having at least 4 decimal points in ColumnName table.
SELECT * FROM TableName WITH (NOLOCK) WHERE ColumnName LIKE '%.____'

SELECT with CASE fail when aggregate function is used

I have the following t-sql query.
DECLARE #Test TABLE(
Points INT
,PointsOf INT
)
INSERT INTO #Test
VALUES (3,12),(2,12),(3,12),(11,12),(12,12),(5,12),(0,12)
DECLARE #Decimal TINYINT = 2
SELECT
CASE #Decimal
WHEN 0 THEN CAST(CAST(SUM(Points) AS DECIMAL(18,0)) / NULLIF(SUM(PointsOf), 0) * 100 AS DECIMAL(18,0))
WHEN 1 THEN CAST(CAST(SUM(Points) AS DECIMAL(18,1)) / NULLIF(SUM(PointsOf), 0) * 100 AS DECIMAL(18,1))
WHEN 2 THEN CAST(CAST(SUM(Points) AS DECIMAL(18,2)) / NULLIF(SUM(PointsOf), 0) * 100 AS DECIMAL(18,2))
END AS Score
FROM #Test
I have an variable #Decimals. When the variable is 0 I need my query to return score in XX format, when its 1 in XX.X format and when its 2 in the XX.XX format.
What happen here is that the CASE enter multiple THEN clauses. When the query above is executed i get 44.86 as result which is correct, but when i change the #Decimals valiable to 0 i get a result 44.00 which is incorect. Its suppose to return just 44 without decimals. The same thing happen when i have #Decimals at 1, it returns 44.90 when it has to be 44.9.
Does any one know why this happen?
As jarlh quite rightly points out the case statement is converting this to the smallest possible data type to hold all the result types. (See the MSDN documentation, specifically the Return Types section)
From my point of view, this is merely a display issue. You want to display 44.9 and not 44.90 (note the trailing zero) when the #decimal variable is set to one.
One way to do this is to add an additional cast to varchar. It's not pretty and not something I would recommend doing but if you insist on doing formatting and UI type things in SQL Server then what can you do?
DECLARE #Test TABLE(
Points INT
,PointsOf INT
)
INSERT INTO #Test
VALUES (3,12),(2,12),(3,12),(11,12),(12,12),(5,12),(0,12)
DECLARE #Decimal TINYINT = 1
SELECT
CASE #Decimal
WHEN 0 THEN cast(Cast(CAST(SUM(Points) AS DECIMAL(18,0)) / NULLIF(SUM(PointsOf), 0) * 100 as decimal(18,0)) as varchar(10))
WHEN 1 THEN cast(Cast(CAST(SUM(Points) AS DECIMAL(18,1)) / NULLIF(SUM(PointsOf), 0) * 100 as decimal(18,1))as varchar(10))
WHEN 2 THEN cast(Cast(CAST(SUM(Points) AS DECIMAL(18,2)) / NULLIF(SUM(PointsOf), 0) * 100 as decimal(18,2))as varchar(10))
END AS Score
FROM #Test
I don't know how MS Server works, but according to the ANSI SQL spec, a column always has one specific data type, which in this case is decimal(20,2), i.e. the smallest data type that can store all of the case's different result types.

Is it possible to store output of calculation in select statement into a variable?

I need to perform a calculation with two values from a query and then store that into a variable. I am wondering how this can be done in SQL. This is what I've attempted thus far:
DECLARE #result DECIMAL
SELECT #result = val2 / val1 from table
There problem is the output is wrong.
SELECT #result
Output: 0
Where as if I don't use a variable the output is correct.
SELECT val2 / val1 from table
Output: 0.0712
Any ideas where I am going wrong here?
The default precision of a decimal is 0 (see here).
Try this:
DECLARE #result float;
SELECT #result = cast(val2 as float) / val1 from table;
SQL Server does integer division when both operands are integers. So, I'm casting it to float. If you really want decimal, then use a better declaration, such as:
DECLARE #result decimal(18, 6);
Finally, your selection is ambiguous when your table has multiple rows. I would suggest:
SELECT top 1 #result = cast(val2 as float) / val1 from table;
Better yet, add an order by clause so you know which row you are getting (unless you know the table has exactly one row).
Your DECIMAL type should be declared with precision. Depending on the data types of val1 and val2, you may also need casts on the val1 and val2 in the calculation, as in the code below:
DECLARE #result DECIMAL(5,2)
SELECT #result = cast(val2 as decimal(5,2)) / cast(val1 as decimal(5,2)) from table
select #result
DECLARE #total dec(12,2), #num int
SET #total = (SELECT SUM(Salary) FROM Employee)