Strange result in Mysql subtraction - mysql

I've a simple table in my Mysql database.
The table T has a column A, of type tinyint unsigned, and lenght 1. I use that column to store some boolean values.
When I try to do some simple arithmetic stuff, I get very strange results, for example:
SELECT A - 1 FROM T
returns 0, correctly, if the value of A is 1, but returns 18446744073709551615 (I think ifs 2^64 - 1) if A is 0.
My question is... why, and how can I fix that?
EDIT: declaring A as Signed solves the problem... But I can't understand why. I get that probably if a column is unsigned, -1 is represented as a very large number (2^n - 1), but if the result is of the same type of the column you select, why a 64 bit number?

Unsigned ints cannot hold a negative value
If you try and subtract 1 from 0 it loops back round to the largest value it can have
http://en.wikipedia.org/wiki/Signedness
Not sure if that makes much sense but let me know if still stuck and will try to explain better!

Unsigned means the variable cannot deal with negative numbers, even if it is involved as part of a calculation in SQL.
Try signed.

Related

MySQL-query to retrieve MAX-value doesnt work for decimal numbers

I have a MySQL table that looks like this:
id layer l_to blank
1 1 10 xyz
0 0 5.5 xyz
I want to get the highest number of column-variable "l_to" that shares column-variable "blank".
I have tried the following SQL-query:
SELECT MAX(l_to), COUNT(layer),l_from FROM layers WHERE blank='xyz'
This works fine, if "l_to" of layer 1 is below 10. If it is ten, the query returns "l_to" from layer 0 (5.5).
Any Idea for why this is, and how can I retrieve the MAX?
#EDIT: Changing Datatype of "l_to" from VARCHAR to DECIMAL (5,1) got me the desired result. Thanks for the answers!
The datatype is not a number for field l_to so 5 is greater than 1 for a string. Probably a varchar. Change field l_to to a Decimal [1].
Only consider casting if you do not have control over the table structure as best practice is the data type reflects the data use in the world. This protects the data integrity of the database, provides helpful functions related to the datatype and ensures intuitive outcomes, like Max function. Casting as a work around for this query will only lead to downstream issues; refactor the structure now if you can.
Reference
Decimal data type suggested in comments by #Akina. Originally suggested float, but Decimal appears to reflect the Use Case better than float, given the limited examples shown.
Cast l_to from string to decimal
SELECT MAX(cast(l_to as DECIMAL(10,2)), COUNT(layer) from FROM layers WHERE blank='xyz'
Use a LIMIT query, and also cast the l_to column to decimal:
SELECT *
FROM layers
WHERE blank = 'xyz'
ORDER BY CAST(l_to AS DECIMAL(12.4)) DESC
LIMIT 1;

Remove trailing decimal values to 1 place in sql server 2008 with money format

I have number in DB column and i want to format this with money,decimal data types.
my query is like below,
SELECT CONVERT(VARCHAR,CAST(CAST(CAST(HouseholdCoverage AS DECIMAL(10,1))/ 12 AS DECIMAL(10,1))
AS money),1) AS HouseholdGoodsInsuredAmount FROM Table
HouseholdCoverage = 1175012
My query returns the value like below,
97,917.70
but i want result as
97,917.7 (only 1 number after decimal places).
If i cast the value as float i am getting error.
I know i can use parsename to separate the values after decimal place and add it again with few modifications. But that is not good i feel.
As well as i know this has to be done in C# application, but this query is already written in sql server 2008, i just want modify it according to requirements.
I just figured it out myself after doing some extensive research.. but dont know performance will be good or bad
SELECT LEFT(CONVERT(VARCHAR,CAST(CAST(CAST(HouseholdCoverage AS DECIMAL(10,1))/ 12 AS DECIMAL(10,1))AS money),1),
len(CONVERT(VARCHAR,CAST(CAST(CAST(HouseholdCoverage AS DECIMAL(10,1))/ 12 AS DECIMAL(10,1))AS money),1))-1)
AS HouseholdGoodsInsuredAmount FROM Table
Now the result is as i expected with 1 decimal places after decimal point,
97,917.7
Just keep is simple. Divide your number by a decimal number and cast the answer as DECIMAL(10,1)
DECLARE #HouseholdCoverage BIGINT = 1175012
SELECT CAST(#HouseholdCoverage/128.0 AS DECIMAL(10,1))
DECIMAL(10,1) will make sure that there will be only 1 number after precision(.)

"null" in mathematical calculations?

I'm trying to make a MySQL query that returns rows where (col_a+col_b-col_c+col_d) != col_e, where all of the columns are decimal and default to null. There is one row that I know of that meets these requirements, but when I ran the query with the above logic as the WHERE clause, the row didn't show up. I noticed that col_c was null, instead of a numerical value, and after changing it to 0 the row showed up when I ran the query.
Why did this happen? I have always assumed that null was interpreted as 0 in an instance such as the above?
NULL (as far as my interpretation goes) is unrepresentable data. The only appropriate tests for null are IS NULL, IS NOT NULL, and several functions made specifically to handle NULL values: http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html
You could say - IFNULL(col_c, 0)+col_d (COALESCE will work identically in this case).
More information on working with NULLs: http://dev.mysql.com/doc/refman/5.0/en/problems-with-null.html
Nate, NULL is NULL. MySQL is not going to do the type conversion automatically for you. A way around for that is change the table's column DEFAULT to 0. Or use a function IFNULL(col_c, 0) into your expression.
;-)
Anytime you do a mathematical calculation where one or more of the values might be NULL you need to account for it in the formula by using a numerical identity operation, since any calculation containing a NULL will have a result of NULL. Here are some common cases:
Addition or Subtraction use 0
ifnull(col1,0)+ifnull(col2,0)
ifnull(col1,0)-ifnull(col2,0)
Multiplication, Division, Exponents, or Modulus use 1
ifnull(col1,1)*ifnull(col2,1)
ifnull(col1,1)/ifnull(col2,1)
power(ifnull(col1,1),ifnull(col2,1))
mod(ifnull(col1,1),ifnull(col2,1))

MySQL - avoid truncating trailing zeros in float datatype

I've got a column for storing float data, i.e.
1.1
11.60
4.23
Unfortunately, 11.60 gets stored as 11.6. I need it to have that extra zero. Do I have to change my datatype to varchar? What's the best way to handle this?
It sounds from the comments that you're storing a product code, so float isn't a good choice for a datatype, as you suggest. Indeed it's not a rendering issue, but we'd misconstrued it from your initial choice of float (thinking you indeed were storing something like money or true decimal).
Go with varchar, as you suspected, as it really is a string value.
Here's how you can do that:
create a new column of type varchar(100) or whatever length is suitable for you
copy the values into the new column from your float column
ALTER TABLE MyTable ADD MyNewColumn VARCHAR(100);
UPDATE MyTable
SET MyNewColumn = FORMAT(MyFloatColumn, 2);
This is a rendering issue, not a data issue. To "solve" it, apply mysql's FORMAT function to your value as you select it:
select FORMAT(my_float_column, 2)
from my_table;
The 2 is the number of decimal places. It will handle (almost) any number of digits to the left of the decimal place.

mysql float data not selecting in where clause

This maybe an easy one but i couldn't get answer.
I need to select float value from table
example table :-
value
10.2
4.5
4.6
4.06
my query
SELECT * FROM table where value = '4.6'
returns empty result set
how can i solve this !
Generally, you should never check equality with floats (unless, potentially, you have the same object). Internally, it is represented with more precision, even if it isn't showing it to you by the time it outputs to the screen. This basic tenet holds true for computing in general.
There are a dozens of schemes for doing this, but here is a simple one, which should make sense:
SELECT * FROM table where value BETWEEN 4.599 AND 4.601
Use decimal instead of float.
A decimal(10,2) will have 2 and only 2 decimal places and can be compared in the same manner as integers.
Especially for monetairy values you should always use decimal, but anywhere where rounding errors are unwanted, decimal is a good choice.
See: http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html
Or
MySQL DECIMAL Data Type Characteristics
Today, I also came across the same situation and get resolved just by using FORMAT function of MySQL, It will return the results that exactly match your WHERE clause.
SELECT * FROM yourtable WHERE FORMAT(`col`,2) = FORMAT(value,2)
Explanation:
FORMAT('col name',precision of floating point number)
Hope it helps.
You can also try query
SELECT * FROM table WHERE value LIKE 4.6;
you write:
SELECT * FROM table where round(value, 1) = 4.6