Why does mysql 'select where clause' query wrongly? - mysql

my sql clause:
SELECT * FROM dev_userdb.ry_usercard where UserIdentity=610528194506235115
The UserIdentity is type of varchar(64).When I execute the query,the result is not what I want,why?

The UserIdentity is type of varchar(64)
Then your query should be using quotes around the value you're querying, e.g.
...userIdentity = '601528194506235115'
The reason for the result you get is explained by the MySQL manual's description of equality comparisons:
The following rules describe how conversion occurs for comparison operations:
If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
If both arguments in a comparison operation are strings, they are compared as strings.
If both arguments are integers, they are compared as integers.
Hexadecimal values are treated as binary strings if not compared to a number.
If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN()! To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
A single-row subquery from a table or tables is not considered a constant. For example, if a subquery returns an integer to be compared to a DATETIME value, the comparison is done as two integers. The integer is not converted to a temporal value. To compare the operands as DATETIME values, use CAST() to explicitly convert the subquery value to DATETIME.
If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point (real) numbers.
Your comparison ends up using that lat rule, floating-point number comparison.
The floating-point numbers used by MySQL are IEEE-754 single-precision ("float") or double-precision ("double") binary floating point; presumably it's using doubles for the above (you'd think they'd say).
IEEE-754 double-precision binary floating point only has roughly 15 digits of decimal precision. Specifically, only some integers greater than 9007199254740992 can be represented (9007199254740993 cannot be, for instance); 601528194506235115 is well into the range where there are large gaps between representable integers. If you try to store 601528194506235115 in a double, the value you get is 601528194506235100; that's also what you get when you try to store 601528194506235117 and 601528194506235118 in doubles. So after '601528194506235117', '601528194506235118', and 601528194506235115 are all converted to doubles in order to compare them in your query, they're all 601528194506235100, and so they're all equal. (FWIW, the next representable integer after 601528194506235100 is 601528194506235300.)
JavaScript's numbers are also doubles, so we can see the effect using JavaScript here on site:
var table = [
'42',
'754',
'601528194506235117',
'601528194506235118',
'27'
];
var matches = table.filter(function(num) {
return +num === 601528194506235115;
});
console.log("matching entries:");
console.log(matches);

UserIdentity type is varchar(64), so you should use quotes around the value.
select * from table_name where UserIdentity = 'value';

Related

Why MySQL automatically converts strings to numbers? [duplicate]

This question already has answers here:
Select matches beginning numbers of string on integer
(2 answers)
Closed 4 years ago.
When I try compare this 65 = '65ae3ee2-aeb2-427f-8381-56db91b94363' mysql returns true, why?
SELECT query * FROM families
WHERE id = '65ae3ee2-aeb2-427f-8381-56db91b94363'
OR fam_code = '65ae3ee2-aeb2-427f-8381-56db91b94363'
returns two records:
id fam_code
65 c648b66e-ae0c-467b-af56-1e6d3c214f2e
92 65ae3ee2-aeb2-427f-8381-56db91b94363
Why is that?
In order to compare numbers with strings, MySQL converts both values to real numbers (stored used the floating-point standard).
The rules are described in the "Type Conversion in Expression Evaluation" documentation page:
The following rules describe how conversion occurs for comparison operations:
If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
If both arguments in a comparison operation are strings, they are compared as strings.
If both arguments are integers, they are compared as integers.
Hexadecimal values are treated as binary strings if not compared to a number.
If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. [...]
If one of the arguments is a decimal value, comparison depends on the other argument. The arguments are compared as decimal values if the other argument is a decimal or integer value, or as floating-point values if the other argument is a floating-point value.
In all other cases, the arguments are compared as floating-point (real) numbers.
The case you described fits into the last item: "in all other cases, the arguments are compared as floating-point (real) numbers".
It returns these two records, why is that?
Because that's how MySQL tries to cast strings to numbers (to check against your integer id). Basically, it reads as much number as it can, and throws the rest away.
65ae3ee2-aeb2-427f-8381-56db91b94363
^^
Can interpret this as a number.
65ae3ee2-aeb2-427f-8381-56db91b94363
^
Garbage starts. Ignore this and the rest of the string.

Yii2: problems with findOne query on float value

Database field name with datatype value float(5,2)
Inserted value
7.80
78.00
My query in modal
$checkValue = static::find()->where(['value' => $this->value])->one();
If i passed $this->valueequal to 78.00 or 78.000 then it returns proper result.
But if I pass 7.80 or 7.8 then 0 rows are returned. Why?
i suspect internally mysql treats 7.8 as something like 7.800000000001 so you cannot get a result if you compare with a fixed value.
you may have come across mysql's reference manuals on datatypes.
please note the following:
MySQL permits a nonstandard syntax: FLOAT(M,D) or REAL(M,D) or DOUBLE PRECISION(M,D). Here, (M,D) means than values can be stored with up to M digits in total, of which D digits may be after the decimal point. For example, a column defined as FLOAT(7,4) will look like -999.9999 when displayed. MySQL performs rounding when storing values, so if you insert 999.00009 into a FLOAT(7,4) column, the approximate result is 999.0001.
Because floating-point values are approximate and not stored as exact values, attempts to treat them as exact in comparisons may lead to problems. They are also subject to platform or implementation dependencies. For more information, see Section B.5.4.8, “Problems with Floating-Point Values”
For maximum portability, code requiring storage of approximate numeric data values should use FLOAT or DOUBLE PRECISION with no specification of precision or number of digits.
for most applications you can safely use a fixed point type.
essentially using decimal(5,2) instead of float(5,2) ensuring that any value displayed is the exact value stored internally.
when applicable rounding happens on insert with the "round half up" rule to the precision you specifed and is somewhat more intuitive and easy to manage
I resolve this issue with double datatype
value double(5,2)

MYSQL: Cant save 1000000 on a float field

I have a float column and I'm trying to save the value 1000000. It automatically turns it to 1e+06. How can I fix it?
To have the value returned formatted as 1000000, you can simply add integer zero to the column in the SELECT list.
SELECT mycol+0 AS mycol FROM mytable
MySQL is storing the value IEEE floating point format. (One bit for sign, a certain number of bits for the exponent, and a certain number of bits for the mantissa. This isn't really a MySQL thing, it's the standard representation for floating point values.)
As far as what's being returned, that's an issue with converting that value into string representation.
A floating point number has a large range of values. To represent the maximum value of a float (3.402823e+38) as a decimal value, that would require 38 decimal digits. The seven left most digits of the value are significant, but we'd need to add another 32 zeros/digits to indicate the position of the decimal point.
So, returning a string representation of scientific notation is a reasonable approach to returning a representation of the value.
Those two things are equivalent:
1e+06
= 1 * 10^6
= 1 * 1,000,000
= 1,000,000
It's called scientific notation (see here). mySQL uses it to display huge/tiny values, especially approximate values (see here).
You can use DOUBLE(8, 3) where 8 is the total no. of digits excluding the decimal point, and 3 is the no. of digits to follow the decimal.

Is it possible to cast a DECIMAL to DOUBLE in MySQL?

I know all the numerical implications, that is, the possible rounding issues inherent to floating point formats, but in my case I have DECIMAL columns in MySQL that I want to convert to DOUBLE straight in the MySQL query rather than down stream.
Could anyone help?
SELECT my_decimal_field + 0E0 FROM my_table
The following quotes from MySQL manual explain how this works:
9.1.2 Numeric Literals
Number literals include exact-value (integer and DECIMAL) literals and approximate-value (floating-point) literals.
Numbers represented in scientific notation with a mantissa and exponent are approximate-value numbers.
12.22.3 Expression Handling
Handling of a numeric expression depends on what kind of values the expression contains:
If any approximate values are present, the expression is approximate and is evaluated using floating-point arithmetic.
Because of the limitations of the built in CAST function in MySQL, it is only possible to convert DECIMAL to DOUBLE with your own user defined cast function.
Sample use case:
SELECT castDecimalAsDouble(0.000000000000000000100000000000);
Result: 1e-23
CREATE DEFINER=`root`#`localhost` FUNCTION `castDecimalAsDouble`(
decimalInput DECIMAL(65,30) ) RETURNS double
DETERMINISTIC
BEGIN
DECLARE doubleOutput DOUBLE;
SET doubleOutput = decimalInput;
RETURN doubleOutput;
END
It seems not possible to cast it to DOUBLE which brings problems if you do calculations and for example want to ROUND() a DECIMAL 12,2 in the third digit. Using ROUND(foo * bar,2) will just ignore the additional digits if your foo and bar are DECIMAL 12,2 fields.
That said you can do something like this to still make it work:
ROUND(CAST(foo AS DECIMAL(30,15)*CAST(bar AS DECIMAL(30,15)),2)
DECIMAL may save space. For example, DECIMAL(4,2) occupies only 2 bytes. FLOAT takes 4; DOUBLE takes 8.
As for the original question, simply do:
ALTER TABLE t MODIFY COLUMN c DOUBLE ...;
(The "..." should include the other stuff you already had, such as NOT NULL.)

Rules for MySQL type conversion

I'm wondering what the rules are for mysql type conversions are. e.g.
select foo/2 from table seems to yield a decimal if the foo column is an int. select sum(foo) from table gives the sum(foo) column back as a double if foo is a float. select i*i from table gives a bigint if i is an int.
What are the rules for the type conversion here when using common operators such as +-/* or aggregates such as sum/avg ?
The rules of type conversion are quite straightforward. Quoting from the MySQL Manual :: Type Conversion in Expression Evaluation:
When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly.
The following rules describe how conversion occurs for comparison operations:
If one or both arguments are NULL, the result of the comparison is NULL, except for the NULL-safe <=> equality comparison operator. For NULL <=> NULL, the result is true. No conversion is needed.
If both arguments in a comparison operation are strings, they are compared as strings.
If both arguments are integers, they are compared as integers.
Hexadecimal values are treated as binary strings if not compared to a number.
If one of the arguments is a TIMESTAMP or DATETIME column and the other argument is a constant, the constant is converted to a timestamp before the comparison is performed. This is done to be more ODBC-friendly. Note that this is not done for the arguments to IN() To be safe, always use complete datetime, date, or time strings when doing comparisons. For example, to achieve best results when using BETWEEN with date or time values, use CAST() to explicitly convert the values to the desired data type.
In all other cases, the arguments are compared as floating-point (real) numbers.
In the case of arithmetic operators, the result is determined according to the following rules. Quoting from the MySQL Manual :: Arithmetic Operators
In the case of -, +, and *, the result is calculated with BIGINT (64-bit) precision if both arguments are integers.
If one of the arguments is an unsigned integer, and the other argument is also an integer, the result is an unsigned integer.
If any of the operands of a +, -, /, *, % is a real or string value, the precision of the result is the precision of the argument with the maximum precision.
In division performed with /, the scale of the result when using two exact values is the scale of the first argument plus the value of the div_precision_increment system variable (which is 4 by default). For example, the result of the expression 5.05 / 0.014 has a scale of six decimal places (360.714286).
Then for aggregate functions, the following applies. Quoting from the MySQL Manual :: Aggregate Functions:
For numeric arguments, the variance and standard deviation functions return a DOUBLE value. The SUM() and AVG() functions return a DECIMAL value for exact-value arguments (integer or DECIMAL), and a DOUBLE value for approximate-value arguments (FLOAT or DOUBLE).