MYSQL - Search in 2 columns with one search term - mysql

I have a search query to search my users table for the search term entered by the user.
My query searches in 3 rows:
user_last_name
user_first_name
user_business_address
Everything works fine as long as the user searches for one of the rows at a time.
Let's say user_first_name is 'Alex' and user_last_name is 'Smith'. If I search for 'Alex' or 'Smith' everything works fine.
The Problem
When the user searches for 'Alex Smith' as soon as the space key is hit there are no results shown anymore.
How can I search in both rows?
How do I deal with the whitespace?
My search query
$term = strip_tags('%'.$_GET['term'].'%');
$query = $database->prepare("SELECT COUNT(*) FROM users WHERE user_last_name LIKE :term OR user_first_name LIKE :term OR user_business_address LIKE :term ORDER BY user_id LIMIT 10");
$query->execute(array(':term' => $term));
$count = $query->fetchColumn();
if ($count >= 1) {
$query2 = $database->prepare("SELECT * FROM users WHERE user_last_name LIKE :term OR user_first_name LIKE :term OR user_business_address LIKE :term ORDER BY user_id LIMIT 10");
$query2->execute(array(':term' => $term));
$results = $query2->fetchAll();
}
Please let me know if you would like to see any more code.
I would be very thankful for any kind of help!

First of all, don't use LIKE to look for an exact match, use a single equal sign (=) .
Secondly, you can use CONCAT to combine first name and last name :
SELECT * FROM users
WHERE concat(user_first_name,' ',user_last_name) = :term
ORDER BY user_id LIMIT 10
I removed the last condition user_business_address like :term since you didn't explain what is it for.
If the user will input either first name/last name or full name, then you can use the LIKE operation with % wildcard :
SELECT * FROM users
WHERE concat(user_first_name,' ',user_last_name) LIKE concat('%',:term,'%')
ORDER BY user_id LIMIT 10"
Here is a document on like operator .

SELECT * from users where user_first_name = SUBSTRING_INDEX(SUBSTRING_INDEX(fullname, ' ', 1), ' ', -1) ,
TRIM( SUBSTR(fullname, LOCATE(' ', fullname)) ) AS last_name FROM registeredusers
There's a bunch of cool things you can do with substr, locate, substring_index, etc. Check the manual for some real confusion. http://dev.mysql.com/doc/refman/5.0/en/string-functions.html

Related

How can we write following mysql query in mongodb? I need to search a text by ignoring some characters from username field stored in users collection

SELECT * FROM users WHERE REPLACE(username, '.', '_') = 'username_without_dots'
I read about $replaceAll but it is not helping.
In my query, first I am replacing existing record and then comparing, e.g there are usernames like
harry.potter
j.k rowling,
robert downy jr.
so what will happen is that DOTs(.) in these names will be replaced by UNDERSCORE( _ ) so the result will be:
harry_potter
j_k rowling,
robert downy jr_
after that comparing with searched string.
So lets say I am searching harry_potter
SELECT * FROM users WHERE REPLACE(username, '.', '_') = 'harry_potter'
Output will be:
harry.potter
Maybe try this:
db.users.find({$and:[{"username":/^[^.]*$/},{"username":"username_without_dots"} ] } )

Mysql - Search by tokenized string

I have a simple request: search by a user name.
Nevertheless, imagine I have this data on database:
1 - John Amazing Doe
2 - John Stupid Doe
3 - John Anthony
When I search by "John Doe", is there an easy way to search by results that have "john" or "doe"? Even better, if we could rank by who has more matches?
Thanks
Prepare the data prior to building the query
This is something that would be best handled a bit programmatically prior to sending to MySQL.
Turn the name into a list, break on space:
"John Doe" --> "John|Doe"
SELECT username FROM users WHERE username RLIKE 'John|Doe'
Be careful about sql injection here.
php Example
$db = new PDO([conn info]);
$searchArg = 'John Doe';
$nameRegex = str_replace(' ','|', strtolower($searchArg));
$userSearch = $db->prepare('SELECT username FROM users WHERE LOWER(username) REGEXP :nameRegex');
$userSearch->bindValue(':nameRegex', $nameRegex, PDO::PARAM::STR);
$userSearch->execute();
foreach ( $userSearch->fetchAll(PDO::FETCH_ASSOC) as $user ) {
echo $user['username'] . '\n<br>';
}
A full text index and MATCH() is your best option. That said, here is another way:
You can search for names that have 'John' or 'Doe' using LIKE:
SELECT user_name
FROM users
WHERE user_name LIKE 'John%'
OR user_name LIKE '%Doe'
Use leading and trailing % only if names will not always start with 'John' or end with 'Doe', otherwise use one. Double % will not make use of any indexes you have on user_name
You can then rank these using UNION and sorting column:
SELECT user_name, 1 as Sort_Col
FROM users
WHERE user_name LIKE 'John%'
AND user_name LIKE '%Doe'
UNION
SELECT user_name, 2 as Sort_Col
FROM users
WHERE (user_name LIKE 'John%'
OR user_name LIKE '%Doe')
AND user_name NOT IN (
SELECT user_name
FROM users
WHERE user_name LIKE 'John%'
AND user_name LIKE '%Doe')
ORDER BY Sort_Col ASC
You'll have to use an annoying NOT IN for the second query to be sure that you don't return rows that have both 'John' and 'Doe'. Normally the UNION would suffice, but since we added Sort_Col it will not. Just another reason to add a full text index if at all possible.

mysql search for 's' ending should return the same without 's' ending

I want to search using MATCH in mysql.
I have 1 table contain "name" and "category" fields. the "category" field contain book,books,books.
what i want is, when i search "book" or "books" in category field, it should give me 3 row.
can anyone help me with this ?
thanks
i need to clarified this question, actually i have a website which have search field. when user input something on it, my web should search in category field. the real problem is, sometimes user input "book", sometimes "books", sometime "car" ,sometimes "cars". these "s" word after the word make me headache, i know that user really want is to find all related with book or car, so, what should i do, should i strip every "s" letter ? or is there any better solution ?
Ari
select *
from table
where category LIKE '%book%'
trim the user input to a acceptable length and try this query
$userInput = substr($input, 0, 4);
select * from table where category like "%$userInput%"
If you are running the query from PHP, for example, you could prepare the query there and then use a simple regular expression:
<?php
$term = 'book';
if(substr($term,-1) == 's') { //if term ends in an s
$term = substr($term,0,-1); //the word without the s
}
//TODO: escape $term to prevent SQL injection
$query = "
SELECT * FROM table
WHERE category REGEXP '{$term}s?' // s? matches zero or one 's' character
";
Searching with MATCH() requires a fulltext index on column category, which might be overkill.
If you really just want those two cases, you could write
select * from table where
category = 'book' or category = 'books'
With Oddant's answer you might also get results like 'probookcover' or whatever.
If you want it to be case insensitive you have multiple options.
select * from table where
lower(category) = 'book' or lower(category) = 'books'
or
select * from table where
category like 'book' or category like 'books'
Alternatively you could also do
select * from table where
category like 'book%'
which gets you all columns which start with book, but you might also get 'bookcover'.
EDIT: Considering your comment:
Like I said, match() is overkill, therefore I would do it like this:
select * from table where
category = whatYourUserEnters OR category = substring(whatYourUserEnters, 1, length(whatYourUserEnters) - 1)

mysql SELECT * FROM table WHERE column+space+column LIKE '%query%'

For a search function, I need to be able to get the mysql function to show up results by combining two columns.
To be more precise: I have a table in the database called "members" in that there is a column called "firstname" and one called "lastname" which I need to use for this. When someone types in a whole name, eg. Jane Doe, I want the query to look whether combining firstname + a space(&nbsp?) + lastname brings forth any results.
My code so far is this:
$poster = mysql_query("SELECT id FROM members WHERE (firstname'&nbsp'lastname) LIKE '%$search%'") or die(mysql_error());
$poster = mysql_fetch_object($poster);
I know that's probably wrong, it's the most recent I've tried after trying with brackets around the firstname + lastname bits, etc, etc... But yes, any help would be greatly appreciated.
Use the CONCAT function:
SELECT id FROM members
WHERE CONCAT(firstname, ' ', lastname) LIKE ?
Try CONCAT
SELECT id FROM members WHERE concat(firstname, ' ', lastname) LIKE '%$search%'
SELECT id FROM members WHERE (firstname + ' ' + lastname) LIKE '%$search%'
I believe what you are looking for is:
$name_var = 'John Doe';
// Example 1 - using concatenation
$sql = "SELECT id FROM members WHERE CONCAT(firstname, ' ', lastname) = '$name_var'";
The above statement will search for everything where the first name is John and the last name is Doe
This is rather ineficcient as it will have to evaluate the CONCAT everytime in mysql I believe
I would reccomend validating in PHP that the string is two words as you expect e.g.
$name_var = 'John Doe';
// this will split the string based on spaces
$names = explode(' ', $name_var);
$first_name = $names[0];
$last_name = $names[1];
// Example 2 - searching each field
$sql = "SELECT id FROM members WHERE firstname = '$first_name' AND lastname = '$last_name'";
The above statement will still search for everything where the first name is John and the last name is Doe
In the above statment you are actually just searching based on the exact values so it is much more efficient. If this query is going to be ran regularly, you should also add indexes to the firstname and lastname fields in your mysql table as it will greatly increase the speed!
hope this helps!
Tom

Grouping multiple MySql queries

I have a simple query as listed below
SELECT id, name, email FROM users WHERE group_id = 1
This works great until, I then start adding LIKE queries, chained with OR statements to the end.
SELECT id, name, email FROM users
WHERE group_id = 1
AND id LIKE $searchterm
OR name LIKE $searchterm
OR email LIKE $searchterm
Suddenly my WHERE clause is no longer upheld and results with a 'group_id' of 2 or 3 are retrieved.
Is there a way I can group WHERE clauses so that they are always upheld or am I missing something obvious?
Dealing with the query first - you need to use brackets for the WHERE clause to be interpreted correctly:
SELECT id, name, email
FROM users
WHERE group_id = 1
AND ( id LIKE $searchterm
OR name LIKE $searchterm
OR email LIKE $searchterm)
I'd be looking at using Full Text Search (FTS) instead, so you could use:
SELECT id, name, email
FROM users
WHERE group_id = 1
AND MATCH(id, name, email) AGAINST ($searchterm)
Mind that the USERS table needs to be MyISAM...
I assume you want
email FROM users WHERE group_id = 1 AND (id LIKE $searchterm OR name LIKE $searchterm OR email LIKE $searchterm)
Here is the mysql operator precedence table