MySQL SUM() always returns a 0 value - mysql

I have amounts stored as a varchar in my table.
When attempting to sum them it always returns 0.00.
Below is an example using only one record from the db.
SELECT col1, SUM(CAST(col2 AS DECIMAL(20,2))) derived1
FROM table
WHERE col3 = 'FIT'
AND col1 = '6211195'
GROUP BY col1
This returns one row with a 0 value.
By removing the SUM and CAST from the query, I can see that it is pulling the value as it should, but I can not sum or cast it, adding either of those breaks it and returns 0 again.
I have also tried converting the field to a decimal type and it just zeros all the values.
EDIT:
Ughh, I just ran a REGEX query to detect anything that isnt an alphanumeric value or a decimal point. It appears that there are non ascii characters in the field that I cant see, messing with the type casting. Will continue to update as I learn more.

Show some sample values of col2. A string that really is a number is treated as a number. Hence '1' will become 1.
However, if the string does not start with a digit, '-', or '+' (after leading spaces), then it will be 0 (in most cases). So 'A1' will be 0. And so on. As will '$100'.
The lesson is: If a column contains numbers, store them as numbers. Really simple.

Related

How to retrieve a value after second hyphen using mysql select query

Below I am using substring index within max attribute in select statement to get max value from a column. But below code works fine for single digits after second dash but it doesn't retrieve value for double digit values after second dash.
Below is the query what i am using
select max(SUBSTRING_INDEX(pid,"-",-1)) from patient;
Values stored in column are of pattern as shown below
P-29082017-1,
P-29082017-2,
...
P-29082017-9,
P-29082017-10
The above query returns only single digit, i,e if i have 10 entries say pid from 1 to 10 listed in column, Value i am getting back from the above query is 9 and not 10
Please suggest where i am going wrong with the query
I think your max() function is being evaluated in string context rather than numeric context. In string context, 9 comes after 10.
So try this. It will turn SUBSTRING() output into numbers.
SELECT MAX(CAST(SUBSTRING_INDEX(pid,'-',-1) AS INT))

Why is CAST function returning first value in comma-separated values, but not zero?

When I executed following query to find the country name by the ID, I accidentally passed a string that contained comma-separated values.
SELECT * FROM country WHERE id='6,AU,+61'
This query fetched that respective row.
When I tried casting this string into UNSIGNED using
SELECT CAST('6,AU,+61' AS UNSIGNED)
It returned 6, the first value.
When I tried integer values separated by comma (for eg: '7,8'), it also returned 7. So, it wasn't taking any values after the first comma.
In case of CAST('AU,+61' AS UNSIGNED), it returned zero.
Isn't '7,8' a string, so why is it not converting this into zero and taking first value instead?
MySql casts string to number by looking at the string from its left most char going right.
If the first char is a digit, it will iterate right until it reaches a non-digit char and will cast it to a number. if the string starts with a non-digit char it will cast to 0.
Thats why CAST('AU,+61' AS UNSIGNED) is 0
While CAST('7,8' AS UNSIGNED) is 7
However, The above is not documented specifically in the MySql Cast reference.
Although there are few examples over there and a specific line that implies such a behavior:
there are many different strings that may convert to the value 1, such as '1', ' 1', or '1a'.
However this can be validated with few simple tests:
SELECT CAST('a7' as UNSIGNED) as 'col_a7'; -- 0
SELECT CAST('7q6' as UNSIGNED) as 'col_7q6'; -- 7
SELECT CAST(' 7q6' as UNSIGNED) as 'col__7q6'; -- 7
SELECT CAST('1.4' as UNSIGNED) as 'col1.4'; -- 1
I might not be so clear in my description above, but these tests should clarify things.

MySQL Case not working ROUND the value

I'm trying to ROUND() or not the selected value. The query looks likes this:
SELECT b.Series,
CASE
WHEN Series = 'DMS' THEN ROUND(b.Quantity,0)
ELSE ROUND(b.Quantity,2)
END AS Quantity
FROM bill b
I also tried
CASE Series
WHEN 'DMS' THEN ROUND(b.Quantity,0)
ELSE ROUND(b.Quantity,2)
END AS Quantity,
and
IF(b.Series = 'DMS', ROUND(b.Quantity,0), ROUND(b.Quantity,2)) AS Quantity,
Every time I get the 2 decimals at the end.
When the Series is 'DMS' Quantity should be like an integer (without decimals), in the other cases Quantity should have two decimals.
In a result set, the data type is an attribute of the column for the entire result set.
For any given column in a result set, the value in that column for each row must necessarily be of the same data type.
The data type of the returned column for this query will, by necessity, be set by the server to something along the lines of DECIMAL(11,2) in order to accommodate all the possible values.
I would anticipate that what you are seeing is actually correctly rounded, but with an "unexpected" .00 at the end.
CAST(CASE ... END AS CHAR) AS Quantity would -- potentially -- get you a result that looks more like you're expecting, by casting everything to a string.
That's obviously some very sloppy type-handling, but it's no more unreasonable than expecting different types to emerge in the same column... which can't be done.
The more correct solution is to return them as two different columns, with two CASE expressions or IF().
ROUND(IF(Series = 'DMS',b.Quantity,NULL),0) AS dms_quantity,
ROUND(IF(Series = 'DMS',NULL,b.Quantity),2) AS non_dms_quantity
Note that both IF() tests evaluate the same expression and have their arguments reversed rather than the second one using != with the arguments the same, so that NULL values for series, if possible, are handled correctly by the second test. (Anything != NULL cannot evaluate to true; the third argument to IF() is used for both FALSE AND NULL results).

Automatic MySQL data type casting

I just happened upon an interesting case of data type casting in MySQL. Consider the following queries:
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col=123; #Yields 0 rows
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col="123"; #Yields 0 rows
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col="0"; #Yields 1 row, col=0
SELECT * FROM (SELECT 0 AS col) AS t WHERE t.col="abc"; #Yields 1 row, col=0
Lines 1, 2, and 3 seem logical to me. But on line 4, why, oh why, dear SQL, do you so eagerly cast "abc" to be equal to 0?!
I mean, I get it - "abc" isn't an integer, so 0 makes the most sense... Is there a scenario in which this behavior is actually useful? As far as I can tell, it likely just leads to bugs (as it did on our application)...
Perhaps there's a MySQL "mode" that enables warnings for automatic type-casting like this?
MySQL does implicit type casting for strings in a numeric context. The leading numeric characters of the string are converted to a number, so a string such as 'abc' gets converted to 0.
This can be very handy because this conversion does not cause an error (an explicit conversion would).
The moral is simple: When comparing constants to columns, make the column the same type as the column. That is, don't compare strings and numbers, lest something unexpected happen.
This is definitely the way MySQL works.
When you use a comparison that compares a numeric object to a string constant, the string gets cast as an integer. MySQL tries to interpret the string as an number, like this:
'0123abc' gets the value 123.
'1abc' gets the value 1.
'abc' gets the value 0.
What use is this? It comes in handy in ORDER BY clauses if you need numeric text strings ordered in numeric order with '112abc' after '12abc'.

What the mysql query difference between =1 and = '1' with enum?

I had a query like
SELECT name, town FROM clients WHERE course = 1;
and it gave me some results.
But i noticed the query didn't output the latest entries. I look into the table clients with phpmyadmin and i saw more course fields with value 1.
After i changed the query to
SELECT name, town FROM clients WHERE course = '1';
i got the right output.
My question: why is this? and why did i get some results with the first query ?
ps: course is an enum field ( '0','1').
1 is either an integer value, or 'TRUE', or ... (ambiguous) while '1' is a string value.
As explained in the MySQL-documentation for the ENUM-type:
An ENUM is a string object with a value chosen from a list of
permitted values that are enumerated explicitly in the column
specification at table creation time.
[...]
If you wish to use a number as an enumeration value, you must enclose
it in quotation marks. If the quotation marks are omitted, the number
is regarded as an index. For this and other reasons—as explained later
in this section—we strongly recommend that you do not use numbers as
enumeration values.
So, ENUM is a string object, therefore you need to reference to it as a string.