filter string only contains q in mysql - 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', '') = ''

Related

Creating GORM dynamic query with optional paramters

I've been stuck on a GORM issue for about a full day now. I need to be able to filter a messages table on any of 4 things: sender, recipient, keyword, and date range. It also has to paginate. Filtering by sender and recipient is working, and so is pagination. So far this is the query that I have come up with, but it does not seem to work for date ranges or keywords.
Here is how I am selecting from MySQL
db.Preload("Thread").Where(query).Scopes(Paginate(r)).Find(&threadMessages)
I am creating the query like this:
var query map[string]interface{}
Then based on which parameters I am passed, I update the query like this by adding new key values to the map:
query = map[string]interface{}{"user_id": sender, "recipient_id": recipient}
For dates it does not seem to work if I try something like this:
query = map[string]interface{}{"created_at > ?": fromDate}
And for a LIKE condition is also does not seem to work:
query = map[string]interface{}{"contents LIKE ?": keyword}
The reason I chose this approach is that I could not seem to get optional inputs to work in .Where since it takes a string with positional parameters and null positional parameters seem to cause MySQL to return an empty array. Has anyone else dealt with a complicated GORM issue like this? Any help is appreciated at this point.
Passing the map[string]interface{} into Where() only appears to work for Equals operations, or IN operations (if a slice is provided as the value instead).
One way to achieve what you want, is to construct a slice of clause.Expression, and append clauses to the slice when you need to. Then, you can simply pass in all of the clauses (using the ... operator to pass in the whole slice) into db.Clauses().
clauses := make([]clause.Expression, 0)
if mustFilterCreatedAt {
clauses = append(clauses, clause.Gt{Column: "created_at", fromDate})
}
if mustFilterContents {
clauses = append(clauses, clause.Like{Column: "contents", Value: keyword})
}
db.Preload("Thread").Clauses(clauses...).Scopes(Paginate(r)).Find(&threadMessages)
Note: If you're trying to search for content that contains keyword, then you should concatenate the wildcard % onto the ends of keyword, otherwise LIKE behaves essentially the same as =:
clause.Like{Column: "contents", Value: "%" + keyword + "%"}
My final solution to this was to create dynamic Where clauses based on which query params were sent from the client like this:
fields := []string{""}
values := []interface{}{}
If, for example, there is a keyword param:
fields = []string{"thread_messages.contents LIKE ?"}
values = []interface{}{"%" + keyword + "%"}
And to use the dynamic clauses in the below query:
db.Preload("Thread", "agency_id = ?", agencyID).Preload("Thread.ThreadUsers", "agency_id = ?", agencyID).Joins("JOIN threads on thread_messages.thread_id = threads.id").Where("threads.agency_id = ?", agencyID).Where(strings.Join(fields, " AND "), values...).Scopes(PaginateMessages(r)).Find(&threadMessages)

How to do a SQL query using a string wildcard and LIKE?

I am new to python and currently learning to use SQL with python. I have the following code:
word = input("Enter a word: ")
query = cursor.execute("SELECT * FROM Dictionary WHERE Expression LIKE '%s%' " % word)
results = cursor.fetchall()
The second line throws an error since I don't think I can use '%s%' like that? How would I change this so as to be able to make this work? I want to be able to return all related entries to the users input. So if the user inputs "rain", then I want the query to return all possible results e.g. "raining", "rainy" etc. Thank you.
You can try
query = cursor.execute(f"SELECT * FROM Dictionary WHERE Expression LIKE '%{word}%' ")
You should use cursor.execute() parameter substitution rather than string formatting, to prevent SQL injection.
Then use CONCAT() to surround the search string with %.
query = cursor.execute("SELECT * FROM Dictionary WHERE Expression LIKE CONCAT('%', %s, '%' "), (word,))

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

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.

REPLACE string in MySQL but only specified part

i would like to replace string in my query but only on the end of the string this is my example:
SET #exampleString = 'example_a_chapter_a';
SELECT REPLACE(#exampleString ,'_a','_b1');
Result what I get is this: example_b1_chapter_b1
But i would like this: example_a_chapter_b1
But there can be more time the '_a' in the string as this 'example_a_type_a_chapter_a', but
i would like to replace just the end '_a' of the string.
Thanks for you help
This will be tricky since MySQL can not replace by regex. One of possible ways is:
SELECT REPLACE(REPLACE(CONCAT(#exampleString, '#END'), '_a#END', '_b1'), '#END', '');
-i.e. add something that 100% is not in original string, to it's end and then replace.
Edit: second REPLACE is needed in case if original string doesn't end with _a (so you'll need to remove added #END)
You could not use replace() at all. Just reconstruct the string:
select (case when #exampleString like '%_a'
then concat(left(#exampleString, length(#exampleString) - length('_a')),
'_b1'
)
else #exampleString
end)
This has the advantage that it works even when the string doesn't end in '_a'.

Convert standard simplified pattern ( * ? ) to the LIKE pattern ( % _ )

I would like to know if there is a better way than :
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE('p%a_t*er?', '\\', '\\\\'), '%', '\%'), '_', '\_'), '*', '%'), '?', '_')
To transform standard search patterns * and ? to the LIKE equivalents % and _ in MySQL ?
There isn't a shorter method to perform multiple-character replacements directly in MySQL. There are alternatives such as User-Defined-Functions (UDFs), but I'm doubtful that any would be beneficial to your exact purpose.
My suggestion would be to perform the text replacement prior-to querying the database, if acceptable.
In PHP, this could be done with:
$searchQuery = $_GET['q'];
$searchQuery = str_replace(array('*', '?'), array('%', '_'), $searchQuery);
// perform your query as normal
In ASP, you could try:
string searchQuery = Request.QueryString["q"];
searchQuery = searchQuery.Replace("*", "%").Replace("?", "_");
// perform your query as normal
Though, both method aren't super-short, they do make it a little easier to read and also won't add any time to your db-query. Also, doing the replacement prior to the query will allow you to replace before the string is sanitized so you won't need to replace the \ as you do in your existing query - which saves you one replacement!
Instead of like you can use regexp of Mysql like this:
select * from my_table where col_name regexp 'p%a_t*er?';
While using regexp there is no need to do all those replacements to make your string like friendly.