MySQL query - select postcode matches - mysql

I need to make a selection based on the first 2 characters of a field, so for example
SELECT * from table WHERE postcode LIKE 'rh%'
But this would select any record that contains those 2 characters at any point in the "postcode" field right? I am in need of a query that just selects the first 2 characters. Any pointerS?
Thanks

Your query is correct. It searches for postcodes starting with "rh".
In contrast, if you wanted to search for postcodes containing the string "rh" anywhere in the field, you would write:
SELECT * from table WHERE postcode LIKE '%rh%'
Edit:
To answer your comment, you can use either or both % and _ for relatively simple searches. As you have noticed already, % matches any number of characters whereas _ matches a single character.
So, in order to match postcodes starting with "RHx " (where x is any character) your query would be:
SELECT * from table WHERE postcode LIKE 'RH_ %'
(mind the space after _). For more complex search patterns, you need to read about regular expressions.
Further reading:
http://dev.mysql.com/doc/refman/5.1/en/pattern-matching.html
http://dev.mysql.com/doc/refman/5.1/en/regexp.html

LIKE '%rh%' will return all rows with 'rh' anywhere
LIKE 'rh%' will return all rows with 'rh' at the beginning
LIKE '%rh' will return all rows with 'rh' at the end.
If you want to get only first two characters 'rh', use MySQL SUBSTR() function
http://dev.mysql.com/doc/refman/5.1/en/string-functions.html#function_substr

Dave, your way seems correct to me (and works on my test data). Using a leading % as well will match anywhere in the string which obviously isn't desirable when dealing with postcodes.

Related

How do I create a SELECT conditional in MySQL where the conditional is the character length of the LIKE match?

I am working on a search function, where the matches are weighted based on certain conditions. One of the conditions I want to add weight to is matches where the character length of the query string in a LIKE match is longer than 4.
This is what I want to the query to look like, roughly. %s is meant to represent the actual match found by LIKE, but I don't think it does. I'm wondering if there is a special variable in MySQL that does represent the precise character match found by LIKE.
SELECT help.*,
IF(CHAR_LENGTH(%s) > 4, 2, 0) w
FROM help
WHERE (
(title LIKE '%this%' OR title LIKE '%testy%' OR title LIKE '%test%') OR
(content LIKE '%this%' OR content LIKE '%testy%' OR content LIKE '%test%')
) LIMIT 1000
edit: I could in the PHP split the search string array into two arrays based on the character length of the elements, with two separate queries that return different values for 'w', then combine the results, but I'd rather not do that, as it seems to me that would be awkward, messy, and slow.
Check out FULLTEXT as another way to discover rows. It will be faster, but won't address your question.
This probably has the effect you want.
SELECT ....
IF ( (title LIKE '%testy%' OR
content LIKE '%testy%'), 2, 0)
....
Note that the "match" in your LIKEs includes the %, so it is the entire length of the string. I don't think that is what you wanted.
REGEXP "(this|testy|that)" will match either 4 or 5 characters (in this example). It may be possible to do something with REGEXP_REPLACE to replace that with the empty string, then see how much it shrank.
I think the answer to my question is that what I wanted to do isn't possible. There is no special variable in MySQL representing the core character match in a WHERE condtional where LIKE is the operator. The match is the contents of the returned data row.
What I did to reach my objective was took the original dynamic list of search tokens, iterated through that list, and performed a search on each token, with the SQL tailored to the conditions that matched each token.
As I did this I built an array of the search results, using the id for the database row as the index for the array. This allowed me to perform calculations with the array elements, while avoiding duplicates.
I'm not posting the PHP code because the original question was about the SQL.

MySQL LIKE Operator with Special Characters Confusion

First let me apologize I have not been successful in finding anything online with this specific scenario.
I have been using MySQL for quite some time, but I am hoping to get some clarification on a certain situation I have come across, which honestly bothers me quite a bit.
I'm trying to match a string in a MySQL column that contains both \ and % literal characters using the LIKE operator.
Inside the table I have two records:
id value
-----------------------
1 100\\%A
2 100\%A
They both contain literal special characters.
If I do a SELECT, in an attempt to only match the first record (id=1), I would expect to write the query as such:
SELECT * FROM table_name WHERE value LIKE '%0\\\\\%A'
(\\\\ to match two literal backslashes, plus a backslash before % to match a literal %)
However, It only matches the row (id=2), which makes no sense to me.
If I change the query a little to be:
SELECT * FROM table_name WHERE value LIKE '%0\\\\%A'
I would expect to match the id=1 row only, (\\\\ to match 2 literal backslashes, and the % is not literal and should represent a wildcard). But instead, it matches both rows?
row (id=2) only has a single backslash but still matches.
Is row id=2 matching because the first 2 backslashes are matching the \, the 3rd backslash is ignored for some reason, and the 4th backslash is allowing a literal match on the %?
If I do a:
SELECT * FROM table_name WHERE value LIKE '%0\\\\\\\%A'
I for some reason get row (id=1), when I would expect to get no matches whatsoever.
I'm trying to find a solution in which I can do partial matches on any series of characters accurately, including those with consecutive special characters such as the scenario above. However, I'm having an impossible time trying to plan for situations such as these.
Any input would be greatly appreciated.
Maybe this help you understand the usage of escape chars in mySQL
https://stackoverflow.com/a/27061961/634698

Why isn't MySQL REGEXP filtering out these values?

So I'm trying to find what "special characters" have been used in my customer names. I'm going through updating this query to find them all one-by-one, but it's still showing all customers with a - despite me trying to exlude that in the query.
Here's the query I'm using:
SELECT * FROM customer WHERE name REGEXP "[^\da-zA-Z\ \.\&\-\(\)\,]+";
This customer (and many others with a dash) are still showing in the query results:
Test-able Software Ltd
What am I missing? Based on that regexp, shouldn't that one be excluded from the query results?
Testing it on https://regex101.com/r/AMOwaj/1 shows there is no match.
Edit - So I want to FIND any which have characters other than the ones in the regex character set. Not exclude any which do have these characters.
Your code checks if the string contains any character that does not belong to the character class, while you want to ensure that none does belong to it.
You can use ^ and $ to check the while string at once:
SELECT * FROM customer WHERE name REGEXP '^[^\da-zA-Z .&\-(),]+$';
This would probably be simpler expressed with NOT, and without negating the character class:
SELECT * FROM customer WHERE name NOT REGEXP '[\da-zA-Z .&\-(),]';
Note that you don't need to escape all the characters within the character class, except probably for -.
Use [0-9] or [[:digit:]] to match digits irrespective of MySQL version.
Use the hyphen where it can't make part of a range construction.
Fix the expression as
SELECT * FROM customer WHERE name REGEXP "[^0-9a-zA-Z .&(),-]+";
If the entire text should match this pattern, enclose with ^ / $:
SELECT * FROM customer WHERE name REGEXP "^[^0-9a-zA-Z .&(),-]+$";
- implies a range except if it is first. (Well, after the "not" (^).)
So use
"[^-0-9a-zA-Z .&(),]"
I removed the + at the end because you don't really care how many; this way it will stop after finding one.

How does % wildcard exactly work in sql when searching

I saw a select statement with something like this in the where part 'LIKE %Blabla%Another%', now I tried it myself and I don't clearly understand how it works. The thing I'm confused about is the % in the middle, I understand how '%Blabla Another%' works, but with the % as a replacement for the space, I got confused.
% means "any sequence of characters, including an empty one". So LIKE '%Blabla%Another%' will match, for example 'XYZBlablaABCAnotherPQR', 'BlablaAnother' and ' Blabla Another '
% means any (including none) chars.
If you have a string 'abcdef' it would match e.g 'a%f' since the string start and ends with a and f.
'%b%e%'would also match as it means any string with b and even, in that order, but not necessarily next to each other
With LIKE you can use the following two wildcard characters in the pattern:
% matches any number of characters, even zero characters.
_ matches exactly one character.
© dev.mysql.com
In SQL, wildcard characters are used with the SQL LIKE operator.
there are the wild cards in sql %,_,[charlist],[^charlist].
the % wild cards is a substitute for zero or more characters.
for example
SELECT * FROM Customers
WHERE City LIKE '%es%';
this will selects all customers with a City containing the pattern "es".
so here you can see that the % wild card act as null or space character.
Here is a listing of the wildcards that you can use and below some examples.
%: A substitute for zero or more characters
_: A substitute for a single character
[charlist]: Sets and ranges of characters to match
[!charlist]: Matches only a character NOT specified within the brackets
The following SQL statement selects all customers with a City containing the pattern "es"
SELECT * FROM Customers WHERE City LIKE '%es%'
The following SQL statement selects all customers with a City starting with any character, followed by "erlin":
SELECT * FROM Customers WHERE City LIKE '_erlin'
The following SQL statement selects all customers with a City starting with "b", "s", or "p":
SELECT * FROM Customers WHERE City LIKE '[bsp]%'
The following SQL statement selects all customers with a City NOT starting with "b", "s", or "p":
SELECT * FROM Customers WHERE City LIKE '[!bsp]%'
Source: http://www.w3schools.com/sql/sql_wildcards.asp

MySQL search within the last 5 characters in a column?

My user table has a column "name" which contains information like this:
Joe Lee
Angela White
I want to search for either first name or last name efficiently. First name is easy, I can do
SELECT * FROM user WHERE name LIKE "ABC%"
But for last name, if I do
SELECT * FROM user WHERE name LIKE "%ABC"
That would be extremely slow.
So I am thinking about counting the characters of the input, for example, "ABC" has 3 characters, and if I can search only the last three characters in name column, that would be great. So I want something like
SELECT * FROM user WHERE substring(name, end-3, end) LIKE "ABC%"
Is there anything in MySQL that can do this?
Thanks so much!
PS. I cannot do fulltext because our search engine doesn't support that.
The reason that
WHERE name LIKE '%ith'
is a slow way to look for 'John Smith' by last name is the same reason that
WHERE Right(name, InStr(name, ' ' )) LIKE 'smi%'
or any other expression on the column is slow. It defeats the use of the index for quick lookup and leaves the MySQL server doing a full table scan or full index scan.
If you were using Oracle (that is, if you worked for a formerly wealthy employer) you could use function indexes. As it is you have to add some extra columns or some other helping data to accelerate your search.
Your smartest move is to split your first and last names into separate columns. Several other people have pointed out good reasons for doing that.
If you can't do that you could try creating an extra column which contains the name string reversed, and create an index on that column. That column will have, for example, 'John Smith' stored as 'htimS nhoJ'. Then you can search as follows.
WHERE nameReversed LIKE CONCAT(REVERSE('ith'),'%')
This search will use the index and be decently fast. I've had good success with it.
You're close. In MySQL you should be able to use InStr(str, substr) and Right(str, index) to do the following:
SELECT * FROM user WHERE Right(name, InStr(name, " ")) LIKE "ABC%"
InStr(name, " ") returns the index of the Space character (you may have to play with the " " syntax). This index is then used in the Right() function to search for only the last name (basically; problems arise when you have multiple names, multiple spaces etc). LIKE "ABC%" would then search for a last name starting with ABC.
You cannot use a fixed index as names that are more than 3 or less than 3 characters long would not return properly as you suggest.
However, as Zane said, it's a much better practise to use seperate fields.
If it is a MyIsam table, you may use Free text search to do the same.
You can use the REGEXP operator:
SELECT * FROM user WHERE name REGEXP "ABC$"
http://dev.mysql.com/doc/refman/5.1/en/regexp.html