I've concatenated 2 fields in a form's drop down list, with the 2 fields being First Name and Last Name; This allowed me to display a person's full name.
The issue is that in the database a person's full name is stored in 2 seperate fields; First Name and Last Name.
I need to match the person's full name (from the dropdown list) to the First Name and Last Name in the DB, however I am struggling to achieve this.
The php code for the concatenated form list is:
<td>
<select name='IndivSurname'>";
while($FullName_row = odbc_fetch_array($sql_run_FullName)){
$IndivFirstName=$FullName_row['FirstName'];
$IndivLastName=$FullName_row['LastName'];
echo"<option value='$IndivIndivId' . '$IndivTenantNdx'> $IndivFirstName $IndivLastName</option>";
}
</select>
</td>
While the SQL statement is:
SELECT EventId, EventTime, Individual, Tenant, TenantName, DeviceName, Comment,
InetDb.dbo.Individuals.FirstName, InetDb.dbo.Individuals.LastName
FROM taclogdata.dbo.Event
LEFT JOIN InetDb.dbo.Tenants
ON taclogdata.dbo.Event.Tenant = InetDb.dbo.Tenants.TenantId
LEFT JOIN InetDb.dbo.Individuals
ON taclogdata.dbo.Event.Individual = InetDb.dbo.Individuals.IndivId
AND taclogdata.dbo.Event.Tenant = InetDb.dbo.Individuals.TenantNdx
WHERE (taclogdata.dbo.Event.EventTime BETWEEN '00:00:00 05/26/2015'
AND '09:00:00 05/26/2015'
AND (taclogdata.dbo.Event.Comment ='Reader entry'
OR taclogdata.dbo.Event.Comment='Reader exit')
AND (InetDb.dbo.Individuals.FirstName = '$IndivFirstName'
AND InetDb.dbo.Individuals.LastName = '$IndivLastName')";
Many thanks in advance
The easiest way to do this, is by splitting the string on the space. However, that introduces a bug if the person has more than one first- or surname. This means that in the cases where we have 3 or more elements in the result of the split, we'll have to add the middle elements to both matches; Seeing as we don't know whether it's a surname or middle name.
That is why I recommend using a different character for the glue in the value attribute, one which is never used in a name. # is one such character.
This leaves you with the following code for the form-generation:
// CF: Added HTML-escaping to prevent XSS-attacks.
$IndivFirstName=htmlspecialchars ($FullName_row['FirstName']);
$IndivLastName=htmlspecialchars ($FullName_row['LastName']);
echo"<option value='{$IndivFirstName}#{$IndivLastName}'> $IndivFirstName $IndivLastName</option>";
In the SQL-statement you can do the following (using prepared statements):
$stmt = $db->prepare ("SELECT EventId, EventTime, Individual, Tenant, TenantName, DeviceName, Comment, InetDb.dbo.Individuals.FirstName, InetDb.dbo.Individuals.LastName
FROM taclogdata.dbo.Event
LEFT JOIN InetDb.dbo.Tenants
ON taclogdata.dbo.Event.Tenant = InetDb.dbo.Tenants.TenantId
LEFT JOIN InetDb.dbo.Individuals
ON taclogdata.dbo.Event.Individual = InetDb.dbo.Individuals.IndivId
AND taclogdata.dbo.Event.Tenant = InetDb.dbo.Individuals.TenantNdx
WHERE (taclogdata.dbo.Event.EventTime BETWEEN '00:00:00 05/26/2015' AND '09:00:00 05/26/2015'
AND (taclogdata.dbo.Event.Comment ='Reader entry' OR taclogdata.dbo.Event.Comment='Reader exit')
AND (InetDb.dbo.Individuals.FirstName = :firstname AND InetDb.dbo.Individuals.LastName = :lastname)");
$name = explode ("#", $_POST['IndivSurname']);
$stmt->exec (array (":firstname" => $name[0], ":lastname" => $name[1]));
Splitting on spaces is not going to be reliable given the number of De Aches and Mc Pains in this world.
The really sure way of doing this is to save the first name and last name in a hidden table within your form (in the same order as your pulldown).
A possible alternative is to concatenate using a not a space but one of the other white space characters like NO BREAK SPACE "\u00A0" which you can then reliably split later.
Ok I solved my problem by POSTing the user's PK rather than his First Name and Last Name individually, and search using those characteristics.
However I introduced the explode function as per the below to separate the concatenated values as per the below:
SQL query selects the IndivId, TenntNdx, individual's first name and last name, however only the first name and last name of the user are displayed in the form's drop down list. The matching IndivId and TenantNdx are posted using the code below:
$sql_FullName = "SELECT IndivId, TenantNdx, FirstName, LastName FROM InetDb.dbo.Individuals
ORDER BY FirstName ASC";
$sql_run_FullName = odbc_exec($conn_general, $sql_FullName);
while($FullName_row = odbc_fetch_array($sql_run_FullName)){
$IndivIndivId = $FullName_row['IndivId'];
$IndivTenantNdx = $FullName_row['TenantNdx'];
$IndivFirstName=$FullName_row['FirstName'];
$IndivLastName=$FullName_row['LastName'];
echo"<option value='$IndivIndivId $IndivTenantNdx'> $IndivFirstName $IndivLastName</option>";
The code above would POST the IndivId and TenantNdx (which form a composite primary key for the individuals table) to the page containing the code below which would then separate the 2 fields and search by the PK rather than the individual's name:
$IndivSurname = $_POST['IndivSurname'];
$explode_sql = explode(" ", $IndivSurname, 2);
$ListIndivId = $explode_sql['0'];
$ListTenantId = $explode_sql['1'];
Related
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
I have a comma separated list stored in one row in a column in a mysql database (eg. phrase1, phrase2, phrase3, phrase4). I want to write a query that will deleted one of the values from that comma separated list, say 'phrase3', and its comma, making the list (phrase1, phrase2, phrase4). Ideas?
The list is generated with the following code if that helps:
$q6 = "UPDATE post SET denied_user = CONCAT_WS(', ',denied_user,'$claimer_id'), denied_time = CONCAT_WS(', ',denied_time,NOW()) WHERE post_id = '$post_id' AND user_id='$user_id' AND denied_user<>'' AND denied_user NOT LIKE '%$claimer_id%' AND post_status='active";
I think I don't understand how 'sort' works, so please don't judge me. I really searched all day long.
I have a movies table with actors column. A column it's named "actors". The actors are links separated by space " ". The order of the links it's very important.
I explode the links into an array which looks like [0]-> link0, [1]->link1, ...
I have the actors table where every actor also has it's movies links. I don't want to make 20 different sql searches so I made a variable with all the links I want, like this ( WHERE actor_link = link1 OR actor_link = link2 OR .. )
The problem is this. The search will probably find first the link7, and so my sorting it's gone. What can I do to keep that order from the movies table. I want to display the actors by popularity in the movie, not the order of my database.
Can you give me another method to search the actors without making 'x' sql searches and still keeping the order?
$actors[] = explode(" ", $row['actors_link']);
$x=0;
$actors2 = '';
while ($actors[0][$x]) {
$actors2 = $actors2 . "`link_imdb_actor` = " . "'".$actors[0][$x]."' OR ";
$x++;
}
$actors2 = substr($actors2, 0, -3);
$sql = "SELECT * FROM `actors` WHERE $actors2";
$sql_result = mysql_query($sql) or die(" ");
while ($row3 = mysql_fetch_array($sql_result)) {
echo $row3['link_imdb_actor'];
}
So, the movie Hotel Transylvania has Adam Sandler, Andy Samberg and Selena Gomez. My search shows Selena Gomez, Andy Samberg, Adam Sandler because this is the order from my database. How can I sort the sql results by the order of the actors array? Thank you!
To expand on Arjan's comment, if you want to be able to actually use the actor data (e.g. search with it) I would recommend at least two more tables. One called actors with the fields actorID, firstName, and lastName. The other table would be castings with the fields castingID, actorID, movieID, and castingOrder.
Each castingID will then link an actor to a movie - this would make for easy searches of every movie a particular actor has been in or every actor in a particular movie.
The castingOrder field can be used to maintain the order you want.
I need your existing code to really get the gist of what's going on.
I will make one suggestion in your query. Instead of saying WHERE actor_link = a OR actor_link = b OR actor_link = c do this instead:
WHERE actor_link IN (link1, link2, link3)
Need a big help from you.
I need an advice from all you good people out there.
I have some contents that i need to display only to few countries.I am okay with getting the user's country with Geoip.i am storing my content in MySQL database with a country_code field.country code can be empty or any single code or group of comma separated values
What i want to do is,
checking country_code and if it is empty, display that content for all users.
if country_code is not empty and only a single value,display content only for the given country_code users.
if country_code is group of comma separated values,display contents for all the comma separated country users.
i have two options for do this
adding data columns for each country separately and display contents
as for example three columns for three countries US,UK,AU and if user's location is US,
$sql=mysql_fetch_array(mysql_query("SELECT * FROM content_table WHERE US=='$country_code'"));
adding country data for single column as country_code and store US,UK,AU and if user's location is US,
$sql=mysql_fetch_array(mysql_query("SELECT * FROM content_table WHERE country_code!=''"));
$pieces = explode(",", $sql['country_code']);
foreach($pieces as $val){
if($country_code=="US")
//display content
}
NOTE:amount of countries may differs according to my needs
what will be the best practice to overcome this,
using different columns to different country make fast search but adding more columns is not good i think
using single column and iterate comma separated values needs more computation
What should i do..??
please advice me on this.. OR do you have any idea better than this..? Thanks
I'd just say - create a countries table
countries
id, code, name
1, UK , United Kingdom
..... and rest of the countries
In your content table just add another column country_id or country_code
Content
id, title, body, country_code
1, some text, more text, 1
then in your sql
just select * from content where country_code = 'UK' or country_id = 1 // depending on which option you go for
OR
create a separate linking table for allowing content for multiple countries
content_country
content_id, country_id
1, 2
1, 1
1, 3
To fetch content your queries use left/right/inner join e.g.
SELECT *
FROM `content` c
LEFT JOIN content_country cc ON cc.content_id = c.id
AND cc.country_id
IN ( 2, 4 )
$sql=mysql_fetch_array(mysql_query("SELECT *
FROM content_table
WHERE country_code = ''
OR country_code REGEXP ',?". $user_country_code .",?'"));
If I understood you well, you want to show elements to the user only if the user country code is in the country_code field or if the country_code is not specified ?
This should do it, even if a database solution would be better.
Try It:
$sql=mysql_fetch_array(mysql_query("SELECT * FROM content_table WHERE country_code!=''"));
$pieces = explode(",", $sql['country_code']);
# No Need to run loop
#foreach($pieces as $val)
#{
# if($country_code=="US") //display content
#}
if(!empty($pieces)) //
{
if(in_array($user_country_code,$pieces ))
{
echo "display content";
}
}
else
{
echo "display content"; // for all country
}
Use in_array() except of loop. I guess you will use in on user login so you will have user_country_code.
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.