Having trouble matching a single character in an SQL table - mysql

I need to use the '_' wildcard to find all id that are only one letter which there are a few of. However when I run my query no rows are returned.
Heres my query:
SELECT *
FROM table
WHERE id LIKE '_';
I have a table lets call Table1 that has two columns, id and name.
id either has 1 or 2 characters to label a name. I'm trying to only find the names where the id is only one character. Heres an example of the table:
id name
A Alfred
AD Andy
B Bob
BC Bridget
I only want to return Alfred and Bob in this example.
I don't want the solution but any advice or ideas would be helpful.
Here is a screenshot of my query:
http://i.imgur.com/EWTfoVI.png?1
And here is a small example of my table:
http://i.imgur.com/urGRZeK.png?1
So in this example of my table I would ideally like only East Asia... to be returned.
I if I search specifically for the character it works but for some strange reason the '_' wildcard doesn't.
For example:
SELECT *
FROM icao
WHERE prefix_code ='Z';
This works.

Try using TRIM
Select *
FROM [Table]
where TRIM(ID) LIKE '_';

In MySQL, the underscore is used to represent a wildcard for a single character. You can read more about that Pattern Matching here.
The way you have it written, your query will pull any rows where the id column is just one single character, you don't need to change anything.
Here is an SQL Fiddle example.
EDIT
One trouble shooting tip is to be sure there is no whitespace before/after the prefix code. If there is, and you need to remove it, add TRIM():
SELECT *
FROM myTable
WHERE TRIM(id) LIKE '_';
Here is an example with TRIM.
EDIT 2
A little explanation to your weird behavior, hopefully. In MySQL, if there is trailing white space on a character, it will still match if you say id = 'Z'; as seen by this fiddle now. However, leading white space will not match this, but will still be corrected by TRIM(), because that removes white space on the front and back end of the varchar.
TL;DR You have trailing white space after Z and that's causing the problem.

The most likely explanation for the behavior you observe is trailing spaces (or other whitespace) in the value. That is, you see one character
'A'
But the value may actually be stored as two (or more) characters.
'A '
To see what's actually stored, you can use the HEX and LENGTH functions.
SELECT t.foo
, LENGTH(t.foo)
, HEX(t.foo)
FROM mytable t
WHERE t.foo LIKE 'A%'
The % is a wildcard for the LIKE operator that matches any number of characters (zero, one or more).
You can use the RTRIM() function to remove trailing spaces...
SELECT RTRIM(t.foo)
, LENGTH(RTRIM(t.foo))
, HEX(RTRIM(t.foo))
FROM mytable t
WHERE t.foo LIKE 'A%'

SELECT *
FROM table
WHERE LENGTH(id)=1

Strange..., in my case works perfectly (I am using mysql 5.5).
Please, try this:
select * from mysql.help_topic where name like '_';
What set you get?

Related

mysql MATCH AGAINST weird characters query

I have a table where the field "company_name" has weird characters, like "à","ö","¬","©","¬","†", etc. I want to return all "company_name"s that contain these characters anywhere within the string. My current query looks like this:
SELECT * FROM table WHERE
MATCH (company_name) AGAINST ('"Ä","à","ö","¬","©","¬","†"' in natural language mode);
But I keep getting no data from the query. I know this can't be the case, as there are definitely examples of them I can find manually. To be clear, the query itself isn't throwing any errors, just not returning any data.
The minimun word length is 3 pr 4 .
you can change it see manial
https://dev.mysql.com/doc/refman/8.0/en/fulltext-fine-tuning.html
or use regular expressiions
SELECT * FROM table WHERE
ompany_name REGEXP '[Äàö¬©¬†]+';
SELECT *
FROM table
WHERE company_name LIKE '%[^0-9a-zA-Z !"#$%&''()*+,\-./:;<=>?#\[\^_`{|}~\]\\]%' ESCAPE '\'
This will find any wacky stuff, including wide characters or 'euro-ASCII' or emoji.

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 to avoid a specific character in MySQL

I have a SQL table, with genetic information (name of the gene, function, strand...)
I want to retrieve the amount of chromosomes (21 as I'm working with the human genome). Problem is that some chromosomes are "repeated". For example:
SELECT DISTINCT chrom FROM table LIMIT 6;
chr1
chr10
chr10_GL383545v1_alt
chr10_GL383546v1_alt
chr11
chr11_JH159136v1_alt
As you can see I have more than one chr10, so if I count the DISTINCT chromosomes I get about 6000.
I've tried using NOT LIKE "_" but didn't work. I've thought I could "force" the result with LIKE "chr1" and so on, but I feel like cheating and is not exactly what I'm searching for. I would like a way to avoid every "_", but running
SELECT COUNT(DISTINCT chrom) NOT LIKE "_" FROM table; gives me back just 1 result...
LEFT is not optimal either, because I would have to specify the length of the string, and, I want a system that I could use without knowing anything about the expected result. So running a LEFT "", 4 and LEFT "", 5 is not what I'm searching for.
Is there a way I can count everything that does NOT CONTAIN a certain character? There's a better strategy?
Thank you very much!
Underscore is a wildcard character itself, so it must be escaped. Furthermore you want to match any characters before and after that underscore character so the % wildcard is needed around the escaped underscore.
SELECT count(chrom) FROM table WHERE chrom NOT LIKE '%\_%`;
Also you could use substring_index() to get distinct string before the underscore and count those:
SELECT COUNT(DISTINCT SUBSTRING_INDEX(chrom, '_', 1)) FROM table;
Although that is almost definitely going to be slower.
The problem with SELECT COUNT(DISTINCT chrom) NOT LIKE "_" FROM table; is the location of the comparison and the lack of the % wildcards in the LIKE comparison string.
Either of the following should work for you:
SELECT COUNT(DISTINCT chrom) FROM table WHERE chrom NOT LIKE '%|_%' ESCAPE '|';
Using ESACPE and specifying an escape character after the LIKE is easier than using \ in many cases since, depending on your scenario, you may need to remember to double escape with \. (or if you are writing this in say php, triple escape)
SELECT COUNT(DISTINCT chrom) FROM table WHERE LOCATE('_', chrom) > 0;
LOCATE() is also easier to use here. But I believe it would be slower than just doing a LIKE. The performance difference is probably pretty insignificant, so in most cases, its just preference.
Use REGEXP if you wish to keep it simple.LIKE is faster though.
SELECT count(chrom) FROM table WHERE chrom NOT REGEXP '_';
I also recommend INSTR which I think will perform better than REGEXP.
SELECT count(chrom) FROM table WHERE INSTR(chrom, '_')=0;

MySQL regex matching rows containing two or more spaces in a row

I am trying to write a MySQL statement which finds and returns the book registrations that contain 2 or more spaces in a row.
The statement below is wrong.
SELECT * FROM book WHERE titles REGEXP '[:space]{2,}';
Since the 2 spaces already meet your condition, you really do not need to check if there are more than 2. Moreover, if you need to match a regular ASCII space (decimal code 32), you do not need a REGEXP operator, you can safely use
SELECT * FROM book WHERE titles LIKE '% %';
LIKE is preferred in all cases where you can use it instead of REGEXP (see MySQL | REGEXP VS Like)
When you need to match numerous whitespace symbols, you can use WHERE titles REGEXP '[[:space:]]{2}' (it will match [ \t\r\n\v\f]), and if you only plan to match tabs and spaces, use WHERE titles REGEXP '[[:blank:]]{2}'. For more details, see POSIX Bracket Expressions.
Note that [:class_name:] should only be used inside a character class (i.e. inside another pair of [...], otherwise, they are not recognized.
Your POSIX class must be,
SELECT * FROM book WHERE titles REGEXP '[[:space:]]{2,}';
No need for ,
SELECT * FROM book WHERE titles REGEXP '[[:space:]]{2}';
You may also use [[:blank:]]
SELECT * FROM book WHERE titles REGEXP '[[:blank:]]{2}';
If you mean just the space character: REGEXP ' '. Or you could use LIKE "% %", which would be faster. (Note: there are 2 blanks in those.)
Otherwise, see http://dev.mysql.com/doc/refman/5.6/en/regexp.html for blank and space.

MySQL query - select postcode matches

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.