I am curious to know , how these queries work in database engine. Specially my focus is on line no 4 and 6.
1.SELECT * FROM tableName
2.SELECT * FROM tableName WHERE 1
3.SELECT * FROM tableName WHERE 123
4.SELECT * FROM tableName WHERE '2xyz'
5.SELECT * FROM tableName WHERE ''
6.SELECT * FROM tableName WHERE 'xyz'
In the above queries 1,2,3,4 are producing same result but 5 and 6 are not producing any result. why? what is diff b/w WHERE '2xyx' and 'xyz'?
How '2xyz' implicitly converted into 2 ?
The where clause evaluates to boolean true (not 0) or false (0) in order to decide if a record is in or out of the resultset.
Cases 2 and 3 retrive all records because the non zero numbers evaluate to true.
Case 3 retrieves all records because during the implicit string to number conversion mysql evaluates the string from left to right character by character. As long as as the characters can be evaluated as a number, mysql will take their value. This includes chopping of leading spaces, interpreting plus or minus signs, decimal points, and so on. So, the string '2xyx' is interpreted as 2, thus boolean true.
Case 4 and 5 do not retrieve any records because the strings' leftmost character cannot be evaluated as a number, so the conversion returns 0, thus boolean false.
Unfortunately, the implicit string to number conversion is not really documented in the MySQL manual. Most of the rules, however, can be deducted from the following part in Type Conversion in Expression Evaluation section of the manual:
For comparisons of a string column with a number, MySQL cannot use an
index on the column to look up the value quickly. If str_col is an
indexed string column, the index cannot be used when performing the
lookup in the following statement:
SELECT * FROM tbl_name WHERE str_col=1;1
The reason for this is that there are many different strings that may
convert to the value 1, such as '1', ' 1', or '1a'.
It is WHERE <condition>, e.g. WHERE col1 = 123. What you have instead is WHERE <number> or WHERE <string>, so there is an expression missing.
What would be possible though is WHERE <boolean>, and this is what MySQL expects. And as MySQL treats booleans like numbers (0 = false, other numbers = true), it looks for a number.
1 and 123 are numbers that result in true.
'2xyz' gets converted to 2, i.e. true.
'' and 'xyz' get converted to 0, i.e. false.
So the latter give you an empty result set as the where condition renders false.
In statement SELECT ... WHERE [where_condition], in where_condition expression you can use any of the functions and operators that MySQL supports, in which string literal is also supported. For strings the comparisons are based on the numeric values of the string unit. When evaluating an expression type conversion is also done.
So in above case the 2xyz gets converted to 2 which is true and hence you get all the records. Its like
SELECT * FROM tableName WHERE 2
and the string xyz gets converted to 0 which is false due to which you get empty result set. Its same as:
SELECT * FROM tableName WHERE 0
Where having condition value. Mysql any number treat as TRUE value and null or '' treat as FALSE.
1.SELECT * FROM tableName -- all record return
2.SELECT * FROM tableName WHERE 1 -- Return true value
3.SELECT * FROM tableName WHERE 123 -- Return true value
4.SELECT * FROM tableName WHERE '2xyz' -- Return true value because there first character is number
5.SELECT * FROM tableName WHERE '' -- false value return
6.SELECT * FROM tableName WHERE 'xyz' -- false value return
Related
Examples:
SELECT *
FROM table t
WHERE t.col1
SELECT *
FROM table t
WHERE t.col1 AND t.col2
Depending the nature of the column these queries behaves differently. In my tests, if the column is of the type integer wont show rows with 0s or nulls for that column, if it string, the query will give no result.
I'd like to understand what these types of where conditions mean. Couldn't find any specification for this in the MySQL manual nor an explanation online.
Thanks.
In your query you are not assigning a valid comparision in the where clause (eg: where t.col1 = 10) .. so the where condtion try to eval a casting for the value in the columns mentioned as boolen
in this case the diffent result is just based on the different casting in boolean of each type
if you firts query based on a integer return always a valid true result so yoi get all the rows in the others with string depending of each string value this can produce no rows ,, partial rows or all rows .. try look at the result for the cast of your column in boolean
SELECT if(t.col1, true, false)
FROM table t
WHERE t.col1
and
SELECT if( t.col1 AND t.col2, true,false)
FROM table t
WHERE t.col1 AND t.col2
Those just aren't proper boolean expressions. Boolean expressions evaluate to either true or false and are of the form where t.col1 = 0 and t.col2 >= 3 for example.
The fact that your statements sometimes return data and sometimes not is due to the fact, that 0 and 1 stands for false and true respectively.
Like you already observed, 0 and NULLs don't return rows because they are treated as false in case of 0 and not comparable in case of NULL. Strings on the other hand are implicitly converted to numbers. If the string starts with a number other than 0, the string is converted to that number in MySQL. If the string starts with anything other than that, it's converted to 0. That's why you don't get results for strings.
I would recommend to not use these "short hand boolean expressions". Always write proper expressions!
According to MySQL Reference Manual - The SET Type
Normally, you search for SET values using the FIND_IN_SET() function or the LIKE operator:
mysql> SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)>0;
According to MySQL Reference Manual
FIND_IN_SET(str,strlist)
Returns a value in the range of 1 to N if the string str is in the string list strlist consisting of N substrings. A string list is a string composed of substrings separated by “,” characters. If the first argument is a constant string and the second is a column of type SET, the FIND_IN_SET() function is optimized to use bit arithmetic. Returns 0 if str is not in strlist or if strlist is the empty string. Returns NULL if either argument is NULL.
Therefore, I think that
SELECT * FROM tbl_name WHERE FIND_IN_SET('value',set_col)
works properly when you want to find value from a set.
So why does example from MySQL Reference Manual explicitly comparing with >0 ?
Is there any difference ?
Consider the following two WHERE clauses:
WHERE FIND_IN_SET('value', set_col) > 0
WHERE FIND_IN_SET('value', set_col)
In the first one, if any of the entries in sel_col contains value, then the return value for FIND_IN_SET() will be some number greater than 0, otherwise it will be 0. In other words, it will return TRUE if the value is found, and FALSE otherwise.
The second WHERE clause will evaluate to either WHERE X, where X is either 1 or greater, if value be found, or 0, if value be not found. In MySQL, the value 0 is synonymous with FALSE, and a positive number of 1 or greater is synonymous with TRUE (see documentation).
So these two WHERE clauses will behave identically.
The expression
SELECT (6000.03 + '00') AS res;
gives the result 6000.03, but the expression
SELECT (6000.00 + '00') AS res;
gives the result 6000. Why is the fractional part discarded in the second expression?
You can't add a string to a number without changing the data type.
MySQL will auto-convert the '00' into a number since you have no explicit date definition in your select.
It will discard the fractional part in the second example as 6000.00 = 6000 = an integer value.
If you do this manipulation in a tables column that is defined as decimal, the fractional part won't be discarded as MySQL won't override your column definitions.
I am running a query on a column postal (type double).
SELECT * FROM `table` WHERE `postal` LIKE 'abcdef'; # returns 1 record
and the same query using = returns 100+ records.
SELECT * FROM `table` WHERE `postal` = 'abcdef'; # returns 107 record
What could be the reason?
You are using LIKE on a DOUBLE field, you should not do that.
LIKE is reserved for pattern matching on strings. Use = for numbers, or convert your digit to a string first using CONVERT and then apply the logic with LIKE.
= compares two values for identity.
LIKE is for pattern matching ie. that is, it matches a string value against a pattern string containing wild-card characters.
Refer here
LIKE will check and return similar values where as = will check for the exact value.
The following things affects the result (not the complete list!)
Implicit conversation
MySQL extension to standard SQL's LIKE operator
In each cases an implicit conversion occours: MySQL tries to convert the values to a common data type. In the first case case 'abcdef' will be converted to double which results to 0. This is why you get 107 records when comparing with equals (=).
SELECT * FROM `table` WHERE `postal` = 'abcdef'; # returns 107 record
You should get exactly the same result by running
SELECT * FROM `table` WHERE `postal` = 0;
In MySQL, LIKE is permitted on numeric expressions. (This is an extension to the standard SQL LIKE.)
This means that SELECT CASE WHEN 10 LIKE '1%' THEN 1 ELSE 0 END is allowed and results to 1 (matched)
To be honest, I'm not sure which double value could match with LIKE operator with the pattern 'abcdef'.
In a MySQL table i have a field, containing this value for a given record : "1908,2315,2316"
Here is my sql Query :
SELECT * FROM mytable WHERE 2316 IN (myfield)
I got 0 results!
I tried this :
SELECT * FROM mytable WHERE 2315 IN (myfield)
Still 0 results
And then i tried this :
SELECT * FROM mytable WHERE 1908 IN (myfield)
Surprisingly i obtained the record when searching with 1908! What should i do to also obtain the record when searching with 2315 and 2316 ? What am i missing ?
Thanks
You appear to be storing comma delimited values in a field. This is bad, bad, bad. You should be using a junction table, with one row per value.
But, sometimes you are stuck with data in a particular structure. If so, MySQL provides the find_in_set() functions.
SELECT *
FROM mytable
WHERE find_in_set(2316, myfield) > 0;
You can't use IN() over comma separated list of no.s its better to normalize your structure first for now you can use find_in_set to find results matching with comma separated string
SELECT * FROM mytable WHERE find_in_set('1908',myfield) > 0
This question has been asked and answered before, but I don't want to hunt for it; this question should be closed as a duplicate. But, to answer your question:
The commas in the string, the column value, are just characters. Those are part of the string. They aren't seen as "separators" between values in the SQL text. The way SQL sees it, the column contains a single value, not a "list" of values.
So, in your query, the IN (field) is equivalent to an equals comparison. It's equivalent to comparing to a string. For example:
... WHERE 2316 = '1908,2315,2316'
And those aren't equal, so the row isn't returned. The "surprisingly" finding of a match, in the case of:
... WHERE 1908 IN ('1908,2315,2316')
that's explained because that string is being evaluated in a numeric context. That is, the comparison returns true, because all of these also true:
... WHERE 1908 = '1908,2315,2316' + 0
... WHERE 1908 = '1908xyz' + 0
... WHERE 1908 = '1907qrs' + 1
(When evaluated in a numeric context, a string gets converted to numeric. It just happens that the string evaluates to a numeric value that equals the integer value it's being comparing to.)
You may be able to make use of the MySQL FIND_IN_SET function. For example:
... WHERE FIND_IN_SET(2316,'1908,2315,2316')
But, please seriously reconsider the design of storing comma separated list. I recommend Bill Karwin's "SQL Antipatterns" book...
http://www.amazon.com/SQL-Antipatterns-Programming-Pragmatic-Programmers/dp/1934356557
In mysql IN clause is utilized as
SELECT * FROM mytable WHERE column_name IN (set_of_values) ;
Mention column name instead of values
Please try
SELECT * FROM mytable WHERE LOCATE(CONCAT (',', 2316 ','), CONCAT (',',myfield,',' ) ) <>0