Usage of Substring in MYSQL - mysql

I am trying to understand the usage of Substring query in mysql
Here is the query that i tried.
select substr('Beautiful',-5) from dual; //output tiful
Is it that when we are giving a negative value, the count is done from the last character..
At the same time when i give the following query
select substr('Beautiful',-5,2) from dual; // outputs ti
Is it that when we are giving a negative value, the count is done from the last character and displays the values 5 and 6 i.e (t & i)..
The problem arises when i the following query
select substr('Beautiful',-5,-2) from dual; // outputs <blank>
I was actually expecting the output as "ut". ; can anyone explain me what is happening here, Is my assessment for the above two queries correct ?

Assuming you're using MySQL 5.x, for function SUBSTRING(str,pos,len) , 3rd parameter len is a non-negative integer > 0. Any other value will result in empty string.
If len is less than 1, the result is the empty string.
Reference: http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_substr

Related

Mysql gives me unrelated results

I am new in Mysql and have a table where I'm going to select based on an integer column, the problem is that when I use an string on this column! I got no error but it gives me back all rows. for example:
SELECT * FROM `News` WHERE Cat='hello' order by id desc limit 20
It gives me 20 rows! what's wrong? did I do anything wrong or it's because of something else?
This is normal behavior for MySql, because in this expression:
Cat='hello'
what happens is an implicit conversion of the string literal 'hello' to INTEGER and as it is described in Type Conversion in Expression Evaluation the result of this conversion is 0, so the expression is equivalent to:
Cat=0
If you want to prevent this conversion you could instead convert the column Cat to string:
WHERE CONVERT(Cat, CHAR) = 'hello'
This way the comparison of Cat and 'hello' will be alphanumerical and will fail.
But if you pass a valid integer, then the correct result will be returned.

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 In clause not giving the right result

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

MySQL Unexpected Result from "in (' ' or ' ')"

What I'm Using: The most recent MySQL on Ubuntu 12.
The Set Up: Suppose I have a table "EmployeePayment" with "Name" and "Hours" for each employee. Suppose I already have it populated with values.
The Question: When I use the command
select * from EmployeePayment where Name in ('');
I get the empty set, as I'd expect. But, when I use
select * from EmployeePayment where Name in ('' or '');
I get the entire table returned. Moreover, if I'm picky and put in the command
select Name, SUM(Hours) from EmployeePayment where Name in ('' or '');
then it only returns whatever is the top name from the table. What's happening with this "in" command?
First off, you need to get rid of the or, the proper syntax for the in clause uses commas to separate the possibilities, such as:
sql> select name from people where status in ('intelligent', 'good looking')
pax
1 row returned
What your current variant is doing is applying the or operator to give you a one-element in-list. See here for more detail.
The reason why you're only getting one row for the aggregated query is because you have no group by clause, so you're grouping all rows. Most DBMS' would then complain about having a non-aggregated column that isn't part of the grouping, but MySQL is a bit fancy-free and footloose with the rules in that regard.
It's obviously grouping over the whole table (as it should) but applying some default aggregating function to the name (which it probably shouldn't, but does according to its documentation).
This MySQL extension is covered here but heed the warning: MySQL can choose any of the myriad possible values for these non-aggregated, non-group-by columns, so it's more useful when you know that all the rows in a given group share the same value for the column.
You're effectively doing this:
select * from EmployeePayment where Name in (0);
The OR expression evaluates to 0, and WHERE Name IN (0); returns all rows. You have to use the proper IN syntax as suggested in the other answers:
SELECT * FROM EmployeePayment WHERE Name IN ('foo', 'bar');
IN uses comma separated values, for example: WHERE Name IN ('tim','beth')
So try WHERE Name IN ('','');
But more importantly, why would you want to check where a value is empty or empty? Or was that just to get the question across?
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html#function_in