SUM() function gives incorrect output - mysql

I have a single table named trust_fund:
trust_fund table
My Query is:
$sql = "SELECT SUM(available_balance) AS total_fund FROM trust_funds WHERE type = 'Admin'";
at first, it displays 100000000 which is correct, but when I update the table (transfered 500 from Admin to Agent), Admin available_balance become 99,999,504 and Agent becomes 500.
There is an extra 4 in Admin Balance. I tried transfering the 500 back to Admin Account and Admin Account becomes 100000008.
The Output of the Query
I am confused because the tables shows correct values, 100000000 and 0, but running the query will give 100000004.
Please help
Table Definition
Column
Type
id
INT(AI)
uid
Text
available_balance
Float
wallet_address
Text
type
Text

Your problem arises from your use of the FLOAT data type for currency.
FLOAT is a poor choice for a currency column because it attracts errors from representation and rounding (See Is floating point math broken?)
Use INT (or BIGINT) if you're working with integer values. Alternatively, use DECIMAL to store and work with exact decimal values.

Related

How to update exact decimal value in mysql database

I am working with mysql. I created a column in database called "balance" and the datatype for this column is "DECIMAL(12,6)".
So whenever I try to update 4 digits after the decimal point then the last two digits are showing random values (e.g. balance is showing 4444.888672 for the following query).
Here is my current query
UPDATE `table` SET `balance` = '4444.8888' WHERE `token_address` = 'abc123'
Sounds like common float overflow issue, where decimal part does not fit into memory and is cut off.
In our system we use INT's instead. So you would save into database 44448888000 and in PHP you would parse it as $row['balance'] / 1000000

How to select one column value, normalize and put to another column in mysql?

In my table, I've got a column call mobile and I need this mobile field value to be normalized and save to another column call formatted_phone. For this purpose, I am using the below MySQL query and unfortunately, it is not working. I am putting my query here, please someone correct it. Thank you.
UPDATE hiring_detail
SET formatted_phone = replace(replace(
replace(replace(replace(replace(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.','')
WHERE mobile IS NOT NULL;
Error what it throws:
SQL Error (1265):Data truncated for column 'formatted_phone' at row 3
mobile column: varchar 50
formatted_phone: bigint 15
Usually, beofre blindly executing UPDATE commands, we do a simply What If analysis first, just run the query as a SELECT so you can inspect the output and importantly, you can compare it to the existing values:
http://sqlfiddle.com/#!9/47723a/2
SELECT mobile, formatted_phone
, REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.','') as test
FROM hiring_detail
WHERE mobile IS NOT NULL;
If that logic works for you (and it does in my tests) then there should be no issue with your UPDATE logic.
UPDATE:
If your error is
SQL Error (1265):Data truncated for column 'formatted_phone' at row 3
Then that means that your formatted phone numbers are longer than the column width for formatted_phone. If you know what the length is, you can truncate your formatted numbers, but with phone numbers, if we remove the actual number, this usually results in phone numbers that cannot be called.
I would recommend instead that you increase the width of the formatted_phone field.
This is an example of a forced truncation:
UPDATE hiring_detail
SET formatted_phone = RIGHT(replace(replace(
replace(replace(replace(replace(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.',''),10)
WHERE mobile IS NOT NULL;
Update #2
given that the column is an int, we need to convert the value into an integer.
UPDATE hiring_detail
SET formatted_phone = CAST(replace(replace(
replace(replace(replace(replace(mobile,'-',''),'+',''),')',''),'(',''),' ',''),'.','') as UNSIGNED INT)
WHERE mobile IS NOT NULL;
Warning: It is NOT advisable to store phone numbers as integers, the leading zeros can be significant in area codes in many localities, by storing as a numeric value this can have significant effects and can result in los of data. It also makes it hard to search for partial matches on the numbers. Almost all operations that you can think of (including sorting) on phone numbers will involve string manipulations, not mathematical or numerical.

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;

How to change the field type of result set from SQL pass-through (SPT)?

I have a mysql table column defined as unit_price float(12,4).
If I assign a value of 0.1234, when I create a remote view with dbsetprop, I can retrieve 0.1234 with myview.unit_price.
However, when I use SQL pass-through (SPT) like this:
sqlexec(nHandle, "select * from table", "oResult")
the result of oResult.unit_price only shows 0.12.
How can I ensure that I return the correct, full value?
Not having explicitly tried, you can do some simple math forcing to create larger precision, such as adding an additional column to your query... something like...
select *, unit_price * 1.00000 as UnitPrice5 from...
This will force the field to be computed to 5 decimal position and MIGHT actually change the result column to properly handle this forced decimal capacity. Then, you would use the "UnitPrice5" column instead of "unit_price"...
Don't know if that would be a big issue for you, but once it is in VFP, you have more control too.
The length of the decimal values are defined in your FoxPro settings. Go to Tools->Options->Regional and set the Decimal Digits to a higher value.

MySQL field type for storing decimals

I'm creating a DB that will hold products with several "height" columns (in meters, for ex 7.79 or 12,8). Never more than 2 digits before and 2 after the decimal point. What field type should I use for this?
If I use decimal(2,2) an try to insert 7.79 in phpmyadmin I get an error saying Warning: #1264 Out of range value for column 'working_height' at row 1
I'll be using this DB for searching, so I have to be able to run a query like "select all products where height is great than 7".
You're looking for decimal(4,2) - in general, decimal(m,n) means m total digits, and n to the right of the decimal point. Docs here.
So a decimal(2,2) can store two total digits, both to the right of the decimal point. This explains the error that you are seeing.
People will say to use decimal(s, d) but how about storing the values as integers, in centimeters instead of meters? Easier to compare (no precision loss).
Just my two cents.
Try DECIMAL(4,2) instead
Refer to: MySQL Numeric Types