Curious outcome using OR statements in MySQL Matching - mysql

I am using a mysql match to grab entries from a mysql table that contain certain keywords in their title column. I used the OR option (+ AND -NOT Nil OR) for the mysql match but it seems to only work using one keyword.
Here's my output:
mysql> SELECT * FROM projects WHERE MATCH (title) AGAINST ('Beautiful' 'birds' 'houses' IN BOOLEAN MODE);
Empty set (0.01 sec)
mysql> SELECT * FROM projects WHERE MATCH (title) AGAINST ('Beautiful' IN BOOLEAN MODE);
+-----------+------------------------+--------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+---------+
| id | title | purl | rurl | rewards |
+-----------+------------------------+--------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+---------+
| 978726622 | Beautiful birds houses | https://www.***** | https://www.**** | 4 |
+-----------+------------------------+--------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+---------+
1 row in set (0.00 sec)
Any thoughts or suggestions on this would be really appreciated. It doesn't make any sense to me that the OR statement is somehow restricting the output. Documentation is here

Related

MySQL string splitting on delimiters

Based on https://stackoverflow.com/a/59666211/4250302 I created the stored function get_enum_item for future processing the lists of possible values in the ENUM() type fields.
It works fine enough, but... but I can't determine what to do if the delimiter itself is the part of a string being split. For example:
(square brackets are for readability)
mysql> set #q=",v1,',v2'" --empty string, "v1", "comma-v2";
mysql> select concat('[',get_enum_item(#q,',',0),']') as item;
+------+
| item |
+------+
| [] |
+------+
it is OK
mysql> select concat('[',get_enum_item(#q,',',1),']') as item;
+------+
| item |
+------+
| [v1] |
+------+
it is also OK
mysql> select concat('[',get_enum_item(#q,',',2),']') as item;
+------+
| item |
+------+
| ['] |
+------+
It is not OK
the #q contains 3 commas, the first two of these are real delimiters, while the last one is the part of the third possible value: "comma-v-two". And I have no idea how to avoid confusion of splitting function. MySQL WorkBench in the "form editor" mode solves this trouble somehow, but how can I solve this with MySQL's code?
Well, I can rely on the fact that the show_columns-like queries show the enums in "hardcoded" manner:
select column_name,column_type
from information_schema.columns
where data_type='enum' and table_name='assemblies';
+--------------+------------------------------------------------------------------+
| COLUMN_NAME | COLUMN_TYPE |
+--------------+------------------------------------------------------------------+
| AssetTagType | enum('','И/Н','Н/Н',',fgg') |
| PCTagType | enum('','И/Н','Н/Н') |
| MonTagType | enum('','И/Н','Н/Н') |
| UPSTagType | enum('','И/Н','Н/Н') |
| OtherTagType | enum('','И/Н','Н/Н') |
| state | enum('в работе','на списание','списано') |
+--------------+------------------------------------------------------------------+
Thus I can try to use ',' as a delimiter, but this will not save me from the case if the "comma-apostrophe" combination is the part of possible value... :-(
The only thing I can imagine is to count apostrophes and if the delimiting comma is after the even number of ''s, then it is the delimiter, while if it follows an odd number of ''s, it is the part of the value.
And I can't invent anything except for dumb scanning the input string inside the loop. But maybe there are some other suggestions to get the values split correctly?
Please, don't suggest use PHP, Python, AWK, and so on. The query will be executed from the Pascal (Lazarus, CodeTyphoon) application, and calling external processors is highly unsafe.
As a last resort, I can process the column_type with Pascal's code, but at first, I must make myself sure that the task is not solvable by MySQL's features.
edit:
select column_type from information_schema.columns
where column_name='assettagtype' and table_name='assemblies';
+------------------------------------------+
| COLUMN_TYPE |
+------------------------------------------+
| enum('','И/Н','Н/Н',''''',fgg','''') |
+------------------------------------------+
1 row in set (0.00 sec)
Fourth field: '',fgg, fifth field: '
set #q="'в работе','на списание','списано'";
WITH RECURSIVE cte as (
select 1 as a union all
select a+1 from cte where a<35
)
select distinct regexp_substr(#q,'''[^,]*''',a) as E from cte;
Too high values for 35 raise an error ERROR 3686 (HY000): Index out of bounds in regular expression search.. (I created a bug for this)
The null value should be filtered out... 😉
output:
E
'в работе'
'на списание'
'списано'
null
EDIT: With some effort, this also works for a more complex example (not for every "staged" example!)
set #q="'в работе','на списание','списано',''',fgg'";
select #q;
WITH RECURSIVE cte as (
select 1 as a union all
select a+1 from cte where a<35
)
select distinct regexp_substr(#q,'(''([^,]|[^''][^''])*'')',a) E from cte;
output:
E
'в работе'
'на списание'
'списано'
''',fgg'

can a mysql select query in C language return a field with the special characters escaped?

1- string = a'b"c\d
2- escaped_string = a\'b\"c\\d
3- make an insert query that inserts escaped_string in some table field.
4- make a select query that returns the inserted value.
The returned value is: a'b"c\d
Is there a way to get the select query to return a\'b\"c\\d ?
(I understand that i can escape it again).
You can use the QUOTE() function of mysql:
mysql> select data from x;
+---------+
| data |
+---------+
| a'b"c\d |
+---------+
1 row in set (0.00 sec)
mysql> select quote(data) from x;
+-------------+
| quote(data) |
+-------------+
| 'a\'b"c\\d' |
+-------------+
1 row in set (0.00 sec)
This should exactly do what you are looking for. Note that the " doesn't need to be escaped here, so QUOTE() doesn't escape it, too.

searching multiple columns with one or more keywords using sql

I have one search box that I would like to have search 6 columns in my schools database when an input is made. So far the search box searches the name field only and returns a match for exact or partial inputs.
I would like to search for a specific city and have all results show up from the name AND city columns (instead of just the name column) and so on.
Say I wanted to search with a zip code, I would like the listings to be all schools in that zip code. And finally if I input 2 words (e.g. penn Philadelphia) I would like all penn schools to show that are in the name column AND city column only. (not just all the penns in the name or every school in Philadelphia) and so on. These may be an elementary questions on the matter but I've been searching for days with no success. Maybe better use of wildcards and the "AND" "OR" clauses would benefit me.
Can someone help me structure a sql query to accomplish this?
this is what I have so far:
SELECT * FROM schools
WHERE (name='%name%' OR address='%name%' OR city='%name%'OR zip='%name%')
There are few ways to do that-
The very basic strategy is to match input with our table columns by the query like as you mentioned -
1. SELECT * FROM table WHERE (name='%name%' or zip='%name%' or city='%name%');
2. SELECT * FROM table WHERE LOCATE(name, GROUP_CONCAT(name,city,zip)) > 0;
3.
SELECT * FROM table WHERE name like '%name%'
UNION
SELECT * FROM table WHERE name like '%name%'
UNION
SELECT * FROM table WHERE name like '%name%';
but suppose the case where input box have the string- "varun bharti" but actual name in database is "varun bal bharti" So when you search you will missed the record. for that case you should break the string by space in to array elements and use these queries for elements or either you can replace the space in name column and match.
set #var=REPLACE ('varun bharti', ' ', '%');
SELECT * FROM table WHERE name like concat('%',#var,'%') or
zip like concat('%',#var,'%') or
city like concat('%',#var,'%');
You can also use regualar expressions for that.
For example input string the day boss get
Hitesh> select * from test;
+--------------------+
| name |
+--------------------+
| i am the boss |
| You will get soon |
| Happy birthday bro |
| the beautiful girl |
| oyee its sunday |
+--------------------+
5 rows in set (0.00 sec)
Hitesh> set #var=CONCAT('.*',REPLACE('the day boss get',' ','.*|.*'),'.*');
Query OK, 0 rows affected (0.00 sec)
Hitesh> select #var;
+----------------------------------+
| #var |
+----------------------------------+
| .*the.*|.*day.*|.*boss.*|.*get.* |
+----------------------------------+
1 row in set (0.00 sec)
Hitesh> select * from test where name REGEXP #var;
+--------------------+
| name |
+--------------------+
| i am the boss |
| You will get soon |
| Happy birthday bro |
| the beautiful girl |
| oyee its sunday |
+--------------------+
5 rows in set (0.00 sec)

MySql: using #variable in select statment takes hundreds times longer

I'm trying to understand a huge performance difference that I'm seeing in equivalent code. Or at least code I think is equivalent.
I have a table with about 10 million records on it. It contains a field, which is indexed defined as:
USPatentNum char(8)
If I set a variable withing MySql to a value, it takes over 218 seconds. The exact same query with a string literal takes under 1/4 of a second.
In the code below, the first select statement (with where USPatentNum = #pn;) takes forever, but the second, with the literal value
(where USPatentNum = '5288812';) is nearly instant
mysql> select #pn := '5288812';
+------------------+
| #pn := '5288812' |
+------------------+
| 5288812 |
+------------------+
1 row in set (0.00 sec)
mysql> select patentId, USPatentNum, grantDate from patents where USPatentNum = #pn;
+----------+-------------+------------+
| patentId | USPatentNum | grantDate |
+----------+-------------+------------+
| 306309 | 5288812 | 1994-02-22 |
+----------+-------------+------------+
1 row in set (3 min 38.17 sec)
mysql> select #pn;
+---------+
| #pn |
+---------+
| 5288812 |
+---------+
1 row in set (0.00 sec)
mysql> select patentId, USPatentNum, grantDate from patents where USPatentNum = '5288812';
+----------+-------------+------------+
| patentId | USPatentNum | grantDate |
+----------+-------------+------------+
| 306309 | 5288812 | 1994-02-22 |
+----------+-------------+------------+
1 row in set (0.21 sec)
Two questions:
Why is the use of the #pn so much slower?
Can I change the select statement so that the performance will be the same?
Declare #pn as char(8) before setting its value.
I suspect it will be a varchar as you do it now. If so, the performance loss is because MySql can't mach the index with your variable.
It doesn't matter whether you use constant or #var. You get different result because the second time MySQL gets results from cache. If you execute once again your scenario but trade places queries with const and with #var you will get them same results (but with another value). First will be slowed, second will be fast.
Hope it helps

About mysql regex,how do I search and return string use mysql regex

My table filed's value is "<script type="text/javascript"src="http://localhost:8080/db/widget/10217EN/F"></script>",
I want to analyse this string and fetch the id 10217,how to do use mysql regex?
I know python regex group function can return the id 10217,but i'm not familiar with mysql regex.
Please help me,Thank you very much.
MySQL regular expressions do not support subpattern extraction. You will probably have better luck iterating over all of the rows in your database and storing the results in a new column.
As far as I know, you can't use MySQL's REGEXP for substring retrieval; it is designed for use in WHERE clauses and is limited to returning 0 or 1 to indicate failure or success at a match.
Since your pattern is pretty well defined, you can probably retrieve the id with a query that uses SUBSTR and LOCATE. It will be a bit of a mess since SUBSTR wants the start index and the length of the substring (it would be easier if it took the end index). Perhaps you could use TRIM to chop off the unwanted trailing part.
This query get the Id from the field
SELECT substring_index(SUBSTRING_INDEX(testvar,'/',-3),'EN',1) from testtab;
where as testtab - is table name , testvar - is field name
inner substring get string starts with last 3 / which is
mysql> SELECT SUBSTRING_INDEX(testvar,'/',-3) from testtab;
+----------------------------+
| SUBSTRING_INDEX(testvar,'/',-3) |
+----------------------------+
| 10217EN/F"> |
| 10222EN/F"> |
+----------------------------+
2 rows in set (0.00 sec)
outer substring get
mysql> SELECT substring_index(SUBSTRING_INDEX(testvar,'/',-3),'EN',1) from testtab;
+----------------------------------------------------+
| substring_index(SUBSTRING_INDEX(testvar,'/',-3),'EN',1) |
+----------------------------------------------------+
| 10217 |
| 10222 |
+----------------------------------------------------+
2 rows in set (0.00 sec)