Search for specific keyword in MYSQL - mysql

I'm almost new to mysql.
I wanted to write a query to search for specific keywords in a column where keywords are separated by the comma. but as I use the following code, it only returns the rows where I only have that specific keyword, not in combination with any other keywords.
In Table q16, I'm looking for a way to select rows that have my keyword in the "Area_of_concern" column, no matter if it's combined with other keywords or not:
SELECT *
FROM `q16`
WHERE area_of_concern like '%more education is needed%'
Here's an input example:
q16_id area of concern
1 more education is needed
2 more enforcement, change in strategy
3 change in strategy
4 more education is needed, change in strategy
5 transportation issue, more enforcement, more education is needed
Where I'm looking to get the rows with the keyword "more education is needed". So I should see row 1, 4,5 in the output

I think you should create a table where you have one column for keywords and one column for where those keywords are used: a foreign key for the q16 table in your case.
It will work much faster that way.
As for your question it is a duplicate of this one here, I believe.
How to search for rows containing a substring?
A quick try: try using double quotes instead of single ones, as in some systems, single quotes don't allow for escapes (special characters) inside them.

Related

In MySQL WHERE clause, how can I check for each item in a comma separated list against another comma separated list that may be ordered differently

I'm trying to write a query to look-up rows which contain one or more of comma-separated values. Please see scenario below:
Table: Events, target row to lookup is called "courses"
The data in the courses column is a comma separated string of course codes.
ABC123,XYZ345,ABC987
ABC123
ABC123,ABC987
XYZ345,ABC123
Now what I want to do is to do a
Select * from events where courses in ("ABC123","XYZ345");
However this returns no results.
What I want is that the where lookup to get me all rows that CONTAINS ABC123 OR XYZ345.
Could someone please help me do this?
You could use like, the % are wildcards.
select *
from events
where courses like "%ABC123%" or courses like "%XYZ345%"
There are other approaches: https://dev.mysql.com/doc/refman/8.0/en/pattern-matching.html
It might also be worth normalising the data so that each value is stored in its own row in another table rather than in a comma separated string, as using like will start to hurt performance as the table grows.
#user3783243 mentions loose matching which is a good point and just one reason why storing data like this isn't the best approach.
One way around it would be to tweak the query above to something like:
select *
from events
where courses like "%ABC123,%" or courses like "%XYZ345,%"
but this poses another problem, are the comma separated values always split by a single comma (ABC123,XYZ345) or is there any whitespace (ABC123, XYZ345).
Another problem pointed out by #GarethD is that the previous approaches won't match the last value of the comma separated string (unless it does have a trailing comma). One way I can think of is to do something like this, but it starts making the query a bit clunky, and also assumes all values are 6 characters in length, at this point, it might be worth using a regular expression.
select *
from events
where courses like "%ABC123,%" or courses like "%XYZ345,%"
or right(courses, 6) = 'ABC123' or right(courses, 6) = 'XYZ345'
If all values are indeed six characters then it might be worth trying other mysql functions such as locate, substring and regexp to try and simplify the query.
Just use FIND_IN_SET()
SELECT columns FROM events WHERE FIND_IN_SET("ABC123", courses) OR FIND_IN_SET("XYZ345", courses)
Better of course would be a normalized table, since you can't use indexes with the current design.

Select the records containing one or more words fully in UPPERCASE

I have a query in MYSql database. I have a table order_det, the table's column remarks_desc contains the entries as follows:
Table structure:
Table: order_det
Columns: rec_id, remarks_desc
Sample records in order_det table
rec_id remarks_desc
_________________________________________________________
1 a specific PROGRAMMING problem
2 A software Algorithm
3 software tools commonly USED by programmers
4 Practical, answerable problems that are unique to the programming profession
5 then you’re in the right place to ask your question
6 to see if your QUESTION has been asked BEFORE
My requirement I want to select only the records which that contains one more more words stored in all uppercase letters. From the above 6 records, I want to select only below 1,3,6 records:
rec_id remarks_desc
__________________________________________________
1 a specific PROGRAMMING problem (it contains one all uppercase word PROGRAMMING)
3 software tools commonly USED by programmers (it contains one all uppercase word USED)
6 to see if your QUESTION has been asked BEFORE (it contains two all uppercase words QUESTION and BEFORE)
I tried to archive this using LIKE, REGEXP but getting incorrect result.
Please help me to get the correct result.
Try:
SELECT rec_id, remarks_desc FROM order_det WHERE remarks_desc REGEXP '(^|[[:blank:]])[[:upper:]][[:upper:]]+([[:blank:]]|$)'
I have assumed that you want to exclude single-letter capitalised words. If you want to exclude capitalised words at the start of the string, you'll need to tweak the regex.
Make sure that your table collation is case sensitive (_cs not _ci)
I used information from http://dev.mysql.com/doc/refman/5.1/en/regexp.html#operator_regexp
However, if you're having to use regular expressions to extract data from a database, it's worth considering whether your database design could be improved.
This is particularly important if you need good performance from the database.
Here is the pretty straight forward stored function which returns amount of words in uppercase in row.
Cons:
it's stored function not pure SQL;
it uses collate
it uses regexp, but you can fill free to get rid of it using another inner loop for it;
it counts all words but you can add break if you reach 2.
Please find the function on the following link (gist.github.com). It doesn't display correctly here.

How to search a word in MySQL table? MATCH AGAINST or LIKE?

I have a table for some companies that may have many branches in different countries. These countries are inserted in countries field.
Now, I have to make a searching system that allows users to find companies that have any branch in a specific country.
My question is: Which one do I have to use ? MATCH AGAINST or LIKE ? The query must search all records to find complete matched items.
attention: Records may have different country name separated with a comma.
MATCH AGAINST clause is used in Full Text Search.
for this you need to create a full text index on search column countries.
full text index search is much faster than LIKE '%country%' serach.
I would change the implementation: having a field that contains multiple values is a bad idea, for example, it's difficult to maintain - how will you implement remove a country from a company ?.
I believe that a better approach would be to have a separate table companies_countries which will have two columns: company_id and country_id, and could have multiple lines per company.
You should use LIKE . Because as #Omesh mentioned MATCH AGAINST clause is used for Full Text Search.. And Full Text Search need entire column for search.

Is MySQL FULLTEXT best solution for partial words?

I have a MySQL MyISAM table containing entries that describe airports. This table contains 3 varchar columns - code, name and tags.
code refers to the airport's code (like JFK and ORD), the name refers to the airport's name (John F Kennedy and O'Hare) and tags specify a semicolon separated list of tags that are associated with the airport (like N.Y.C;New York; and Chicago;).
I need to be able to lookup an airport (for an autocomplete) by either the code, name or tags, therefore I set a FULLTEXT index on (code, name, tags).
I have encountered two problems with FULLTEXT so far that prevent me from working with it:
1. There is no way to do partial matching - only postfix matching (is this true?)
2. When a period ('.') is specified in the term to match against, the matching works differently. I am assuming that the period is being parsed in a special way. For example, doing a FULLTEXT search on N.Y.C will not return JFK, although doing the same search on New York will
Is there anyway to overcome these barriers? Otherwise, should I be looking at like matching instead, or an entirely different storage engine? Thanks!
Best solution I came up with is using both FULLTEXT and like matching, and using UNION for the results.

Selecting a column that is also a keyword in MySQL

For some reason, the developers at a new company I'm working for decided to name their columns "ignore" and "exists". Now when I run MySQL queries with those words in the where clause, I get a syntax error; however, I can't seem to figure out how to reference those columns without running into an error. I tried setting them as strings, but that doesn't make any sense.
Help?
Also, is there a term for this kind of mismatch?
put the names in backticks:
`ignore`, `exists`
If you're working across multiple tables or databases you need to escape the database name, table name, and field name separately (if each matches a keyword):
SELECT * FROM `db1`.`table1`
LEFT JOIN `db2`.`table2` on `db1`.`table1`.`field1`=`db2`.`table2`.`field2`
Only the portions that actually match a keyword have to be escaped, so things like:
select * from `db1`.table
are ok too.
The official term is "idiocy" :-) You can put backticks around the names such as
`ignore`
but I would give serious consideration to changing the names if possible. Backticks are not standard SQL, and I prefer my column names to be a little more expressive. For example, ignoreThisUser or orderExists (the general rule I try to follow is to have a noun and a verb in there somewhere).
Interestingly, some DBMS' can figure out not to treat it as a reserved word based on context. For example, DB2/z allows the rather hideous:
> CREATE TABLE SELECT ( SELECT VARCHAR(10) );
> INSERT INTO SELECT VALUES ('HELLO');
> SELECT SELECT FROM SELECT;
SELECT
---------+---------+---------+--------
HELLO
DSNE610I NUMBER OF ROWS DISPLAYED IS 1