Strip special characters and space of a DB column to compare in rails - mysql

I have 4 types of last_name:
"Camp Bell"
"CAMPBELL"
"CampBellJr."
"camp bell jr."
Now, in rails when an user is searched by it's last name like camp bell, I want to show all the 4 records. So, I tried:
RAILS
stripped_name = params[last_name].gsub(/\W/, '')
#=> "campbell"
User.where("LOWER(REPLACE(last_name, '/\W/', '')) LIKE ?", "#{stripped_name}%")
Give me only 2 records with following last_name:
"CAMPBELL"
"CampBellJr."
I guess, this is because, the mysql REPLACE is not working correctly with regex.
Any ideas?
EDIT
Guys, sorry for the confusion. My idea is to strip off all special characters including space. So I'm trying to use \W regex.
For example, the input can be: camp~bell... But, it should still fetch result.

You can check for both stripped_name without space and ones that include both names seperated with space like this.
stripped_name = params[last_name].gsub(/\W/, '')
split_names = params[last_name].split(" ")
User.where('name LIKE ? OR (name LIKE ? AND name LIKE ?)', "%#{stripped_name}%", "%#{split_names[0]}%", "%#{split_names[1]}%")
Next step would to search for complete array of split names not just first two.

Here my solution:
User.where("REPLACE(last_name, ' ', '') ILIKE CONCAT ('%', REPLACE('?', ' ', ''),'%')", stripped_name)
ILIKE is like LIKE but the I is for insensitive case.
To understand easily step by step:
lastname ILIKE '%campbell% you need % because you want lastname
contain this string, not necessary at the begin or the end of you
string.
'campbell%' => search string who begin by campbell
'%campbell' => search string who finish by campbell
We need generate '%campbell%, so we use CONCAT for that
I just use a simply REPLACE, but maybe you should use a regex.

Related

How to parse keywords and strings from a line of text

Have a file keywords.tx with
Commands:
keywords = 'this' & 'way'
;
StartWords:
keywords = 'bag'
;
Then a file mygram.tx with
import keywords
MyModel:
keyword*=StartWords[' ']
name+=Word[' ']
;
Word:
text=STRING
;
'''
My data file has one line with "bag hello soda this way".
Would like to see result have attributes of keyword='bag' name='hello soda' and command='this way'.
Not sure how to get grammar to handle: keywords words keywords making sure that 2nd keywords are not included in the words. Another way to express is startwords words commands
If I understood your goal you can do something like this:
from textx import metamodel_from_str
mm = metamodel_from_str('''
File:
lines+=Line;
Line:
start=StartWord
words+=Word
command=Command;
StartWord:
'bag' | 'something';
Command:
'this way' | 'that way';
Word:
!Command ID;
''')
input = '''
bag hello soda this way
bag hello soda that way
something hello this foo this way
'''
model = mm.model_from_str(input)
assert len(model.lines) == 3
l = model.lines[1]
assert l.start == 'bag'
assert l.words == ['hello', 'soda']
assert l.command == 'that way'
There are several things to note:
You don't have to specify [' '] as a separator rule in your repetitions as by default whitespaces are skipped,
To specify alternatives use |,
You can use a syntactic predicate ! to check if something is ahead and proceed only if it isn't. In the rule Word this is used to assure that commands are not consumed by the Word repetition in the Line rule.
You can add more start words and commands simply by adding more alternatives to these rules,
If you want to be more permissive and capture commands even if user specified multiple whitespaces between command words (e.g. this way) you can either use regex matches or e.g. specify match like:
Command:
'this ' 'way' | 'that ' 'way';
which will match a single space as a part of this and than arbitrary number of whitespaces before way which will be thrown away.
There is a comprehensive documentation with examples on the textX site so I suggest to take a look and go through some of the provided examples.

filter string only contains q in mysql

I need help in mysql query, i written this query
select * from post where content REGEXP '^q'
this query is working but it also includes spaces in filter, what i want to do if any content string like "qqqqqq" or "qqqq" or "qqq" or "qq" or "q" for this string only it should have to filter, right now what is happening if i have string like "qqqq qq" then also it is giving me the result, it should not consider that space, can anyone please help me to resolve this issue ?
You can fix your regexp like next:
select * from post where content REGEXP '^q+$';
This regular expression mean the string starts with q and contain only 1 or more q symbols till end of string
Test it on SQLize.online
Try Using this ^q+(?![\s])+$ Regular Expression.
Above RegExp will check for string starting with q and without space.
You don't really need a regex for this. String functions are likely to be more efficient. You can replace all "q"s with empty strings, and ensure that that resulting string is empty:
select * from post where replace(content, 'q', '') = ''
Note that this also allows the empty string. If you want to avoid that, then:
select * from post where content <> '' and replace(content, 'q', '') = ''

Use DB::select + binding too select a row

I'm trying to get a row from the database but when using binding. I know that this doesn't work because the query automatically puts single quotes so it will be like this: select model, magazine, round('name', 2) etc. This doesn't work of course but how do I get rid of the single quotes?
$merkinformation = DB::select('select Model, Magazine, round(?, 2) as Rondetijd from rondetijden where Merk = ? order by ? limit 3;', [$track, $merk, $track]);
You can't use column nmaes like this.
You must concatinate the name of the column. But this is vulnerable to sql injection. So you must check if $track has a valid content
$merkinformation = DB::select('select Model, Magazine, round(`' . $track . '` , 2) as Rondetijd from rondetijden where Merk = ? order by ? limit 3;', [$merk, $track]);
there is ['] single quote and [`] punctuation mark. If start with single quote or double quote mysql will translate that as string where punctuation mark will be recognize as field name.
Are you sure that is a single quote ?

Using the trim function to narrow down results set

I need to gather data from two columns, concat them so that it's only the first six of the first column and the last six of the second column, separated by ' + '. Some have been input with weird spaces in front or in back, so we must also use the trim feature and get rid of all NULL. I haven't had any issues with the first part, but am struggling to use the trim feature in a way that gives the desired output.
Output needs to look like this:
Input Data sample:
The following code returns results, but the output doesn't match so I know the trim is wrong:
SELECT CONCAT(SUBSTRING(baseball, 1, 6), ' + ',
SUBSTRING(football, -6)) AS MYSTRING
FROM datenumtest2
WHERE baseball IS NOT NULL AND football IS NOT NULL;
I also tried the following, but get an error message about the parameters being incorrect:
SELECT CONCAT(SUBSTRING(LTRIM(baseball, 1, 6)), ' + ',
SUBSTRING(RTRIM(football, -6))) AS MYSTRING
FROM datenumtest2
WHERE baseball IS NOT NULL AND
football IS NOT NULL;
I'm still new to this site and learning, but I have tried to include as much as I can! If there is other information that I can add to help, please let me know.
You just need to use Trim() on the column(s), before using Substring() function on them:
SELECT CONCAT(SUBSTRING(TRIM(baseball), 1, 6), ' + ',
SUBSTRING(TRIM(football), -6)) AS MYSTRING
FROM datenumtest2
WHERE baseball IS NOT NULL AND
football IS NOT NULL;

Repeat word with delete and space in MySQL query

Not sure if this is possible in MySQL, but I have a column that has business names like:
AT&T Store
O'Reilly's Auto Parts
Burger King
which I import into Sphinx Search with a MySQL query. I have MariaDB, so there is a REGEXP_REPLACE(col, regexp, replace) function, but I'm having trouble figuring out the rest.
What I need is to repeat words with non-alphanumeric characters replaced with and without a space. So the above examples would become:
ATT AT T Store
OReillys O Reilly s Auto Parts
Burger King
Is this possible in a MySQL query? Thanks!
This can be done all at once, but maybe not by SQL primitive regex.
I don't know REGEXP_REPLACE, nor modern day SQL.
Typically its done by three regex.
Pseudo code:
$column_val = "O'Reilly's Auto Parts";
$new_column_val = Replace_Globally(
$column_val,
'\b\w+[[:punct:]](?:[[:punct:]]*\w)+\b',
function( $match ) {
$val = $match.value;
$text1 = Replace_Globally( $val, '[[:punct:]]+', "" );
$text2 = Replace_Globally( $val, '[[:punct:]]+', " " );
return $text1 + " " + $text2;
}
);
So, this might not look like something sql can do, so you might have to get creative.
REGEXP_REPLACE is in MariaDB only, MySQL doesn't have it.
select regexp_replace(regexp_replace(
"AT&T Store
O'Reilly's Auto Parts
Burger King",
'([[:alnum:]]+)[[:punct:]]+([[:alnum:]]+)[[:punct:]]+([[:alnum:]]+)',
'\\1\\2\\3 \\1 \\2 \\3'),
'([[:alnum:]]+)[[:punct:]]+([[:alnum:]]+)',
'\\1\\2 \\1 \\2')