Viewed   153 times

I would like to search my table having a column of first names and a column of last names. I currently accept a search term from a field and compare it against both columns, one at a time with

    select * from table where first_name like '%$search_term%' or 
    last_name like '%$search_term%';

This works fine with single word search terms but the result set includes everyone with the name "Larry". But if someone enters a first name then a space, then a last name, I want a narrower search result. I've tried the following without success.

    select * from table where first_name like '%$search_term%' or last_name 
    like '%$search_term%' or concat_ws(' ',first_name,last_name) 
    like '%$search_term%';

Any advice?

EDIT: The name I'm testing with is "Larry Smith". The db stores "Larry" in the "first_name" column, and "Smith" in the "last_name" column. The data is clean, no extra spaces and the search term is trimmed left and right.

EDIT 2: I tried Robert Gamble's answer out this morning. His is very similar to what I was running last night. I can't explain it, but this morning it works. The only difference I can think of is that last night I ran the concat function as the third "or" segment of my search query (after looking through first_name and last_name). This morning I ran it as the last segment after looking through the above as well as addresses and business names.

Does running a mysql function at the end of a query work better than in the middle?

 Answers

5

What you have should work but can be reduced to:

select * from table where concat_ws(' ',first_name,last_name) 
like '%$search_term%';

Can you provide an example name and search term where this doesn't work?

Monday, September 12, 2022
2

I would say just build it yourself. You can set it up like this:

$query = "INSERT INTO x (a,b,c) VALUES ";
foreach ($arr as $item) {
  $query .= "('".$item[0]."','".$item[1]."','".$item[2]."'),";
}
$query = rtrim($query,",");//remove the extra comma
//execute query

Don't forget to escape quotes if it's necessary.

Also, be careful that there's not too much data being sent at once. You may have to execute it in chunks instead of all at once.

Saturday, November 5, 2022
2

The function you're looking for is find_in_set:

 select * from ... where find_in_set($word, pets)

for multi-word queries you'll need to test each word and AND (or OR) the tests:

  where find_in_set($word1, pets) AND find_in_set($word2, pets) etc 
Wednesday, August 17, 2022
3

You need to assign an alias, and test it in the HAVING clause:

SELECT id, @var := id * 2 AS id_times_2
FROM user
HAVING id_times_2 < 10

Note that if you're just using the formula for filtering, not for communicating internal results from one row to the next, you don't need the variable at all. You can write:

SELECT id, id * 2 AS id_times_2
FROM user
HAVING id_times_2 < 10
Wednesday, October 12, 2022
 
1
SELECT users.username, users.id, count(tahminler.tahmin)as tahmins_no 
FROM users 
LEFT JOIN tahminler ON users.id = tahminler.user_id  
where year(timestamp) = 2013 and month(timestamp) = 9
GROUP BY users.id 
having count(tahminler.tahmin) > 0

To make it work with indexes you can do

SELECT users.username, users.id, count(tahminler.tahmin)as tahmins_no 
FROM users 
LEFT JOIN tahminler ON users.id = tahminler.user_id  
where timestamp >= '2013-09-01' and timestamp < '2013-10-01'
GROUP BY users.id 
having count(tahminler.tahmin) > 0
Monday, November 7, 2022
 
gfrigon
 
Only authorized users can answer the search term. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :