Where field1 + field2 + field3 LIKE "%my_own_string%"? - php

I have a string, like Elton 1999, and a MySql table with 4 fields :
table(id, name, surname, year)
I have to check if, joining these fields as "single field", it contains all the words of my string.
I mean :
1 Elton John 1999 -> must return the record
2 Elton Peter 1999 -> must return the record
3 Paris Elton 1999 -> must return the record
4 Elto John 1999 -> must not return the record
5 Elton Pierre 2000 -> must not return the record
Can I do it directly with MySql or I need first to get all the records and than parse them on server side? (on PHP, in my case)
P.S. The same result must begin if my string is 1999 Elton, so the order of my words doesnt matter...

SELECT * FROM myTbl WHERE CONCAT(name, surname, year) LIKE '%ELTON%1999'
or
SELECT * FROM myTbl WHERE CONCAT_WS(' ', name, surname, year) LIKE '%ELTON%1999'
to add a space between each of the fields. Thx majic bunnie.
Update: Well, if you want to search for possible matches on any column with a string of values in any order, then you could explode your string by space and search each word individually. See if this works
$query = "SELECT * FROM myTbl";
if(!empty($searchString)){
$query .= " WHERE ";
$arr = explode(' ', $searchString);
foreach($arr as $word)
$fields[] = "CONCAT_WS(' ', name, surname, year) LIKE %$word%";
$query .= implode(" AND ", $fields);
}
PS - I recently learned this query building technique from #yahyaE here :)

As long as your input strings are consistently formatted, you should be able to join the fields together using CONCAT_WS() with a space as the separator and compare them to your input string when querying.

Related

Using age and gender to search for ID numbers in a table

In an interface where user records in a table can be searched.
The operator must be able to search by the age and/or the gender of the user(the record). However this must be done by using the ID number of the user captured.
This is possible, as the ID number can be broken down into usable data.
An ID number has 13 DIGITS:
eg. 6911205062080
Which can be broken down as follows:
YYMMDDSSSSCAZ
Where (YYMMDD) refers to date. 20 November 1969 is shown as 691120
(SSSS) refers to gender. Females are assigned numbers in the range 0000-4999 and males from 5000-9999
CAZ also carries meaning however they are not relevant to the context of the question. `
The user can choose to search All ages, or select from three age brackets:
A:18-38, B:39-59, C:60 upwards.
-They can select one option[ A or B or C]
-Or They can select two options[A and B,A and C or B and C],
-Or They can select all 3 options[A and B and C], meaning all of them)
This means that if they op not to search all of the age groups, an array containing their selection gets posted.
When selecting gender:
-They can search all genders[Male & Female]
-Or Choose one option [Either Male or Female]
The data gets sent to me and now I have to manipulate the data to return the correct records.
Now I know I have to use substrings. The ID field is stored as character varying however to establish the age I would have to substring the (YYMMDD) part and cast it to a date in order to correctly compare it, and the (SSSS) would have to be cast to an integer to establish if it is smaller than 5000
This is my code so far:
if($_POST['gender'] == 'all'){
$gender="";
}elseif($_POST['gender'] == 'male'){
$gender = " and userIDNumber = "."ESTABLISH ALL ID's THAT ARE MALE";
}elseif($_POST['gender'] == 'female'){
$gender = " and userIDNumber = "."ESTABLISH ALL ID's THAT ARE FEMALE";
}
$age = "";
if($_POST['radioAge'] == 'select'){
$branches = " and userIDNumber in (SELECT A WAY TO FIND OUT HOW TO ESTABLISH THE AGES THAT FALL IN THE GROUPS SPECIFIED BY THIS ARRAY in(". implode(",", $_POST['age_group']).")) ";
}
$query = "SELECT * FROM user_table WHERE status='Active'".$gender.$age;
Using PHP and SQL, how would I go about using the posted gender selections and age selections to find the correct ID numbers and as a result, the correct records?
for the gender try something like this:
if($_POST['gender'] == 'all'){
$gender="";
}elseif($_POST['gender'] == 'male'){
$gender = "and CONVERT(SUBSTR(userIDNumber, 6, 4), INTEGER) < 5000";
}elseif($_POST['gender'] == 'female'){
$gender = "and CONVERT(SUBSTR(userIDNumber, 6, 4), INTEGER) >= 5000";
}
First you need to extract the information from the ID-s for the year part:
You need to use substring and string contatenation for this.
After that you need convert it to date and use the now() function to get the date difference. SELECT DATEDIFF(year, '2011-10-02', '2012-01-01');
Finaly you need to create between branches like this:
... where DATEDIFF(year, '2011-10-02', now()) between 18 and 38 ...
Gender:
Same way, extract the information from id with substring, cast it to numeric.
... where CAST(substring(ID) as numeric) <5000 --female
You also need to create the AND , OR operators.

Insert one array value to a mysql insert statement

People enter values into a form and on one entry of the form I have multiple values.
Eg:
One Entry for Name
and Multiple entries for hobbies.
I could enter into the db by running a for loop but then that would be multiple entries for the same name for each different hobby.
How can I enter one name and all hobbies with 'space' into one DB field 'TWIG'. I could use arrays but it shows up as ARRAY but then its back to FOR loop.
for ($t=0; $t<=$_POST['tc']-1; $t++) {
echo "<BR> ts:".$_POST[$t]."<BR>";
$ths[]=$_POST[$t];
}
print_r ($ths);
$statement = $link->prepare("INSERT INTO quest(cnos, dte, twig)
VALUES(:q, :d, :t )");
$statement->execute(array(
":q" => htmlspecialchars ($_POST['iht']),
":d" => $_SERVER['REQUEST_TIME'],
":t"=> $ths
));
One possibility is to implode your hobbies / concatinate your string into one...
for ($t=0; $t<=$_POST['tc']-1; $t++) {
$ths = $_POST[$t] . " "; //Concatinate string, do no use array!
}
//Cut off last character " " to avoid ugly space at the end:
$ths = substr($ths, 0, strlen($ths) - 1);
However a more clean solution is to make a more clear database structure if you want for atomic values.
This is an 1:n relation (Each of your entries in table A relates to n instances in table B).
Here is an example that can be adapted into your schema very easy:
Table User(id[PK], name, age);
Table User_Hobbies: (user_id, hobby_descr);
--
INSERT INTO User(2, "Chris", 19);
INSERT INTO USER_User_Hobbies(2, "videogames");
INSERT INTO USER_User_Hobbies(2, "music");
--
Example query:
SELECT u.name, u.age, GROUP_CONCAT(uh.hobby_descr) AS hobbies
FROM User u
LEFT JOIN User_Hobbies uh ON u.id = uh.user_id
WHERE u.id = 123 /*Where is optional, if you want to filter for a specific user*/
GROUP BY u.id;
Possible result:
| name | age | hobbies |
chris 18 videogames, music
steve 22 computer, programming, php
Use the implode function for this as follows:
":t"=> implode(" ", $ths);
I am not sure, if I understand your question right, but if you want to insert an array as a comma-seperated string (or separated by whatever), why don't use the php implode function: http://php.net/manual/de/function.implode.php
For example:
$myHobbies = array("football", "basketball", "running");
$statement = $link->prepare("INSERT INTO quest(cnos, dte, twig)
VALUES(:q, :d, :t )");
$statement->execute(array(
":q" => htmlspecialchars ($_POST['iht']),
":d" => $_SERVER['REQUEST_TIME'],
":t"=> implode(" ", $myHobbies)
));
I think to use comma's or semicolons as separator, is better than whitespaces, since some of the hobbies could consists of two words (for example "pc gaming").
I think that better solution is to use json_encode and not implode, since it provides more robust structure.
":t" => json_encode($myHobbies)
You can use join function to store multiple value in same field in database may be it will works:-
":t"=>join(",", $ths);//if you want ,(coma) between two string
or
":t"=>join(" ", $ths);//if you want space between two string

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";

PHP MySQL extract field then split at double spaces

I have a table which contains rows, within each row there is a field which contains peoples names seperated by a double space.
I need to extract this field from each row, then split the field into separate names and dump into another table.
What's the best way to do this? Do I split it within the sql query or extract the fields then split using PHP?
New info:
OK, the field contains full names e.g. john doe, tom smith etc etc the double spaces separate the full names e.g.
JOHN DOE TOM SMITH JOHN WOO
There might be one name in the field but there could also be potentialy up to 10
Thanks
Darren
you can do it in sql. should be something like this:
INSERT INTO tbl_dest (first_name, last_name) VALUES
(SELECT
LEFT(ts.name, LOCATE(' ',ts.name)) AS first_name,
SUBSTRING(ts.name, LOCATE(' ',ts.name)+2) AS last_name
FROM tbl_source AS ts)
as #Marc B stated, it will only work if the data is consistent (ie each row's name field contains a double space and the first double space separates the name and password.
you can ignore other rows (without the double space) by simply adding
INSERT ...
(SELECT ...
FROM tbl_source AS ts WHERE LOCATE(' ', ts.name) > 0)
if the field starts with a double space (ie first name is empty) it will also be ignored
EDIT:
since you said that each row can contain multiple pairs of first/last name. here's a code example:
$query = "SELECT `name` FROM `tbl_source`";
$res = mysql_query($query, $link);
$names = array();
while ($row = mysql_fetch_assoc($res)) {
$nmlist = explode(' ',$row['name']);
for($i=0, $n=count($nmlist); $i<$n-1; $i+=2){
$names[] = "('" . mysql_real_escape_string(stripslashes($nmlist[$i])) ."',"
."'" . mysql_real_escape_string(stripslashes($nmlist[$i+1])) ."')";
}
}
$insert_query = "INSERT INTO `tbl_dest` (`first_name`,`last_name`) VALUES "
.implode(',', $names);
mysql_query($insert_query, $link);
in this example, double spaces are between first name and last name, and between each pair
I'm not familiar with a MySQL solution for this.
I suggest grabbing the information you need, using explode(' ', $info); and then inserting back into the database.

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