Find text with select in 2 columns mySQL/PHP - php

I am making an autocomplete form and requesting names from my database. This is the table in my database
user_id | firstname | lastname
I can get the data for a "searchterm" using this
$query = "SELECT user_id, firstname, lastname FROM users WHERE firstname like :searchterm ";
But I want to expand it so I could also search both firstname and lastname at the same time, for example, to search for "John D...". I think there is a way to join the two columns and then make a search. Can someone explain it?. I am just starting with this mysql thing.

When you've got spaces in your search term, you'll often need to split the string into sections before you put it into your query. Use AND if you want to match all inputted search terms, or OR if you want to match any. Example:
Search: john james smith
<?php
$search = "john james smith";
$bits = explode(" ", $search);
foreach($bits as $key => $bit) {
$bits[$key] = '(`field1` LIKE "' . $bit . '" AND `field2` LIKE "' . $bit . '")';
}
$sql = implode(' OR ', $bits);
// (`field1` LIKE "john" AND `field2` LIKE "john") OR (`field1` LIKE "james" AND `field2` LIKE "james") OR (`field1` LIKE "smith" AND `field2` LIKE "smith")
?>
Demo: https://eval.in/66808
Looks like you're using PDO (which is good), so you'll just need to put your binding parameters into that string instead, then concatenate it on at the end of your current SQL query into the WHERE clause.

Related

Matching variable to two columns joined (PHP)

A previous variable from a query gave me a value $name. I need to find the user id associated with that name, however in my users table I have two fields, firstName and lastName.
I cannot explode $name as I have both cases of double names (e.g. John Eric Smith) and last names (e.g. Jan van der Worde), so my attempt was to find a way to match firstName + lastName with $name.
My attempt was this:
$drid = "SELECT id FROM users WHERE CONCAT(firstName,' ',lastName)='$name'";
$rest = mysql_query($drid);
while ($row = mysql_fetch_row($rest)) {
$driver_id = $row[0];
}
Unfortunately, nothing comes out as a result for $driver_id (whereas $name returns a result).
Thank you for your help!
Are you looking for something like this:
<?php
$drid = "SELECT id FROM users WHERE CONCAT(firstName, ' ', lastName) LIKE '%".$name."%'";
$rest = mysql_query($drid);
while ($row = mysql_fetch_row($rest)) {
$driver_id = $row[0];
}
?>
I would suggest adding a new fullname field or using a temp table rather than using the concat, for performance reasons.
https://stackoverflow.com/a/29285246/3923450 should work though if you are looking for a temp solution

Use REGEX in user input variable in SQL Query.

I have to write a sql query with a where clause which looks for user input values in database table.
Say a user input a job title "Head of science and maths"
The query should look for all the words in a job title individually, and return department list accordingly.
$keyword = mysql_real_escape_string($keyword);
SELECT distinct departments.name FROM departments, jobtitle_keywords
WHERE jobtitle_keywords.keywords REGEXP '$keyword'
AND departments.id = jobtitle_keywords.dept_id;
This query runs perfectly in ideal situations( no special characters , spaces etc ) but fails otherwise
can anyone guide me to a proper way to escape all kinds of special characters and anomalies a user can input so my query does not fail.
Any help is greatly appreciated.
Thanks
So taken your comments i assume you want to take the single words from your users search input (i.e "head of science / math") and use only the words (head, of, science and math) and use those to search for in your jobtitle_keywords.keywords field.
Assuming this is what you want/need:
Use a simple regex to make sure you get all words out of your query like this:
$re = '/(\w+)/i';
$str = 'head of science / math';
preg_match_all($re, $str, $matches);
now in $matches[0] you have your results: array( "head", "of", "science", "math"). Awfully simple.
Now use this to create an SQL Statement using either AND or OR. You can do so easily using implode.
$queryAddon = "jobtitle_keywords.keywords LIKE '%"
. implode ("%' AND jobtitle_keywords.keywords LIKE '%", $matches[0])
. "%'";
Gives you jobtitle_keywords.keywords LIKE '%head%' AND jobtitle_keywords.keywords LIKE '%of%' AND jobtitle_keywords.keywords LIKE '%science%' AND jobtitle_keywords.keywords LIKE '%math%'.
Like stealing a Childs Candy right?
So now just put that in your Query and fire it up.
$query = "SELECT distinct departments.name FROM departments, jobtitle_keywords " ."WHERE departments.id = jobtitle_keywords.dept_id " ." AND (" . $queryAddon . ")";
This should do the trick for you - if i got you right.

Searching full name or first or last name in MySQL database with first and last name in separate columns

I'm working with an existing database that has first name and last name seperated in the database. I need to create a function that will take one search input and return results. say my database has a structure like....
nameFirst nameLast
Joe Smith
Joe Jones
Joe Brown
How could I, using MySql, take a search input that is say 'Joe Smith' and just get his row? But if I put just 'Joe' in the search field, return them all? Will I need to explode the string with a space? thanks!
SELECT *
FROM table
WHERE CONCAT( nameFirst, ' ', nameLast ) LIKE '%Joe%'
Be sure to sanitize any user submitted parameters such as "Joe"
SELECT * FROM table WHERE CONCAT(nameFirst, ' ', nameLast) LIKE 'Joe%';
I suggest to use this if you are sure that your search input start with "Joe" to filter more.
In my humble opinion in a lot of cases we don't know if the search input is the name or the surname so I suggest to use this:
SELECT * FROM table WHERE CONCAT(nameFirst, ' ', nameLast) LIKE 'SEARCH_INPUT%' OR CONCAT(nameLast, ' ', nameFirst) LIKE 'SEARCH_INPUT%';
$sql = "SELECT * from add_contact WHERE ( CONCAT(first_name, ' ',last_name) LIKE '%$search%' OR first_name LIKE '%$search%' OR last_name LIKE '%$search%' OR company LIKE '%$search%') AND (archives='$archives') ORDER BY UNIX_TIMESTAMP(sort_date) DESC";

SQL condition: (A=B AND C LIKE %D%) OR (A LIKE %B% AND C=D)

I've got a table of first names and last names.
I'm trying to make a jQuery instant search on an input, in order to find very quickly and precisely a person in a huge list of people.
When the first word is entered in the input, it might be the first name or the last name.
I do this : SELECT * FROM myTable WHERE firstName LIKE %content% OR lastName LIKE %content%
When two words are entered, it might be:
* the full firstname and a bit of the lastname
* the full lastname and a bit of the firstame
So I tried this query : SELECT * FROM myTable WHERE (firstName = content1 AND lastName LIKE %content2%) OR ( lastName = content1 AND firstName LIKE %content2%)
Unfortunately parenthesis seems to do nothing, and the query is not interpreted this way, I've got a lot of results, basically produced by the two LIKE %% condition
Anyone had deal with this before and could give me a hand?
Thanx
If one of the words is going to be the full first name of the full last name, while the other word is a partial of the other, why don't you split up the words first? Then you'd pass in two paramaters and have:
SELECT
*
FROM
myTable
WHERE
(
firstName = %content1%
AND lastName LIKE %content2%
) OR (
lastName = %content1%
AND firstName LIKE %content2%
)
I believe you are going to need to split the two words entered and use them indepenently in your query.
It would probably work this way (assuming that the two words are in the content variable):
SELECT ... WHERE
CONCAT(firstName, " ", lastName) LIKE content%
OR CONCAT(lastName, " ", firstName) LIKE content%
however this approach would not be very efficient (no index usage). I would split the two words into two variables (word1, word2) and make it something like:
SELECT ... WHERE
(firstName = word1 AND lastName LIKE word2%)
OR (lastName = word1 AND firstName LIKE word2%)
SELECT * FROM myTable WHERE
(firstName = 'content1' AND lastName LIKE content2%)
OR
(lastName = 'content1' AND firstName LIKE content2%)
When two words are entered, it might
be: * the full firstname and a bit of
the lastname * the full lastname and a
bit of the firstame
If it is ALL of (exact match) the first or last name, then the = test seems correct. Just in case it is an error in the PHP part, this is how it should look like.
$qry = '
SELECT * FROM myTable
WHERE (firstName = content1 AND lastName LIKE '%".mysql_real_escape_string(content2)."%')
OR ( lastName = content1 AND firstName LIKE '%".mysql_real_escape_string(content2)."%')';
If it is a bit of both, then you need the wildcard twice
$qry = '
SELECT * FROM myTable
WHERE (firstName LIKE '%".mysql_real_escape_string(content1)."%' AND lastName LIKE '%".mysql_real_escape_string(content2)."%')
OR ( lastName LIKE '%".mysql_real_escape_string(content1)."%' AND firstName LIKE '%".mysql_real_escape_string(content2)."%')';

filter mySQL database with multiple words in any order in Concatenated field

I have Concatenated in mySQL to produce a field that I can search with. This contains animal as well as owner names and addresses for a client database. I need to be able to search by animal name, owner names and postcode in any order.
Thus if if my name is john smith and i own a dog called Fido and live in postcode AB1 2CD, I want the search to be yield results if any of the following are entered:
"john fido AB1"
"john AB1"
"AB1 john"
"AB1 fido"
"fido 2CD"
"2CD"
"fido"
etc... i.e any of the fields in any order, and also not complete words either so "john fido AB1" should yield the same result as "jo fi AB1"
I currently have this PHP code, taking a single text field on my search page, exploding then imploding it to add % between the search terms:
$list = explode(' ',$_GET["q"]);
$q = implode('%%', $list);
if (!$q) return;
$sql = "SELECT DISTINCT owner.AddressPrim, owner.PostcodePrim,
owner.OwnerSurnamePrim,owner.OwnerForenamesPrim,owner.OwnerID
FROM owner
Inner Join patient ON owner.OwnerID = patient.OwnerID
WHERE CONCAT_WS(' ',owner.AddressPrim, owner.PostcodePrim,
owner.OwnerForenamesPrim,owner.OwnerSurnamePrim,patient.AnimalName) LIKE '%$q%'";
This works for "AB1 john" and "john fido" but not "fido john" as it is out of order in the concatenated field.
Any help greatly appreciated
I think you're going to have to split the keywords and add a query for each keyword in the string of keywords.
So first (in PHP), split the query string and dynamically generate your SQL query, then send it to the database. Here's some pseudocode to show you what I mean:
$keywords = explode(' ', $q);
$sql = "SELECT DISTINCT owner.AddressPrim, owner.PostcodePrim,
owner.OwnerSurnamePrim,owner.OwnerForenamesPrim,
owner.OwnerID
FROM owner
Inner Join patient ON owner.OwnerID = patient.OwnerID";
$first = true;
foreach($keyword in $keywords):
if($first):
$sql += " WHERE ";
$first = false;
else:
$sql += " AND ";
$escaped = mysql_real_escape_string($keyword);
$sql += " CONCAT_WS(' ',owner.AddressPrim, owner.PostcodePrim,
owner.OwnerForenamesPrim,owner.OwnerSurnamePrim,patient.AnimalName)
LIKE '%$escaped%'";
But do beware, this is not going to be anywhere near fast for the size of tables you'll probably encounter in daily operation. You may want to look into a better way of doing fulltext search, whether it means using a library or making a cross-reference table of keywords maintained by triggers.
MySQL's fulltext search (MyISAM tables only!) could be useful to you.
http://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
You can try this http://www.sphinxsearch.com/
You need dedicated server to run this thing, but if you have one, sphinx will easily solve your problem and your queries won't load database.

Categories