How do I select a cell with multiple values in one column? - php
I have an MYSQL table with a large product list. In this product list table there are categories, a name, description, text, etc. I want to add a modifier for the industries that it can be used in (e.g. hospitals, schools, events, sport events, etc.)
I'm running this query through PHP/MYSQL right now:
public function GetIndustrySeries($identifier, $SeriesIDArray = null)
{
$query = "select ser.Identifier,
ser.ModelNumber,
ser.Title,
ser.Caption,
ser.Description,
ser.Picture,
ser.Industry,
cat.TitleText,
ser.AutoID,
ser.BasePrice
from ProductSeries ser
inner join
ProductIndustry cat
on
cat.Industry
=
ser.Industry
where
ser.Industry
like
?";
if($SeriesIDArray != null && count($SeriesIDArray) > 0)
$query .= " and ";
$i = count($SeriesIDArray);
$parameters = array();
$parameters[0] = "s";
$parameters[1] = $identifier;
if($SeriesIDArray != null){
foreach($SeriesIDArray as $id)
{
$parameters[0] .= "i";
array_push($parameters, $id);
$query .= " ser.AutoID = ?";
if($i > 1)
$query .= " or ";
$i--;
}
}
$stmt = $this->_mysqli->prepare($query);
//$stmt->bind_param('ss', $identifier);
call_user_func_array(array($stmt,'bind_param'), $parameters);
$stmt->execute();
$stmt->bind_result($ident2, $model, $title, $caption, $description, $picture, $ident, $catText, $sid, $price);
$stmt->store_result();
if($stmt->num_rows < 1)
{
$stmt->close();
return null;
}
$array = array();
while($stmt->fetch())
{
array_push($array, array('seriesLink' => "/products/$ident2/$model", 'seriesTitle' => $title, 'seriesImage' => $picture, 'seriesCaption' => $caption, 'seriesDescription' => $description, "seriesCategoryName" => $catText, "seriesID" => $sid, "basePrice" => $price));
}
$stmt->close();
return $array;
}
I've tried using the % modifier in that code on both sides of the ? but I'm getting an error down the line:
Warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'Array' was given in C:\wamp\www\database.php on line 70.
In the table I have a column for "Industry" and what I want to do is put the industries that the product qualifies for in there hoping it can accept multiple values: "school,hotel,hospital"
You are using the wrong method to get the data. call_user_func calls a method (see http://au.php.net/call_user_func). You want to query the data using mysql functions (http://au.php.net/manual/en/book.mysql.php), PDO (http://au.php.net/manual/en/book.pdo.php) or a data abstraction layer such as zend_db, doctrine, etc.
Would seem to me to be a lot easier just to loop through the array of industries wanted and rather than doing a 'LIKE' doing
$i=0
$query......
....WHERE ( ser.Industry = '".$industry(i)."'";
i++;
while $industry(i) {
$query.=" OR ser.Industry = '".$industry(i)."'";
i++;
}
$query.=")";
Re-reading your question however it seems you need an intermediate table with a two part key, column 1 would be the industry and column two the product, you would then have the key for the product and the key for the industry and all you would need to do is select the rows from your category table where there was a record in the new table with the indusrty you were seeking, or all the rows from the new table which had the category from the first table to see all industries the category fitted, or all rows from the new table for an industry to see all categories that matched.
It seems you could do with more tables since category looks like one table, industry another and product yet another another. Remember the first rule, the data should be dependent on the key, the whole key and nothing but the key.
Hope this helps.
SteveK
It was a combination of my tables not having the same values under the Industry as well as the $identifier part in $paramters[1]; Also some I had to modify some parts of the query string.
Thanks for your help
Related
Foreach nested in a while loop with PDO query
To trim the fat so-to-speak in my script I decided to use 1 PDO prepare to span an array of predefined tables. The PDO executes in a while loop and within the while loop there is a foreach to build the output of each result set. This is code for a search. The script currently searches 3 tables for results (through the while iterations). We will call them tables a, b, and c. For the tested search it finds 2 results in table a, 0 in table b, and 1 in table c. Though it finds a total of 3 results it only displays 2. One from table 'a' and one from table 'c'. The script is not building the result from the second find in the table 'a'. I have looked it over until my eyes bleed and searched for maybe something I have wrong, I cant figure it out. Any ideas of what is wrong with this code? // --- Build an array of places to search $tableArray = array("services", "webPages", "dsiu"); $tableCount = count($tableArray); $count = "0"; $resCount = "0"; $result = ""; while ($tableCount > $count) { // -- Search tables in the array for matches $quotedString = $db->quote($searchString); $qSQL = "SELECT title, ldesc, SUM(MATCH(title, sdesc, ldesc) AGAINST(:string IN BOOLEAN MODE)) AS score FROM ".$tableArray[$count]." WHERE MATCH (title, sdesc, ldesc) AGAINST (:string IN BOOLEAN MODE) ORDER BY score DESC"; $q = $db->prepare($qSQL); $q->execute(array(':string'=>$quotedString)); // -- keep a count of the results $rowCount = $q->rowCount(); if ($rowCount > 0) { $resCount = $resCount + $rowCount; // -- build result html $html = $q->fetchAll(PDO::FETCH_ASSOC); foreach ($html as $row) { // --- Clean the results for display $desc = cleanURL($row['ldesc']); $desc = str_ireplace($searchString, '<b><font color="green">'.$searchString.'</font></b>', $desc); $desc = substr($desc, 0, 300)."..."; $result .= "<font color='red'><b>".$row['title']."</b></font><br>".$desc."<br><br>"; } } $count++; }
Thanks #dan08. I added a if ($row['score'] != null) { to the foreach. Also discovered that SUM() in the query was removing what should have been results. This is now working with the changes.
How to insert data in table from RETS search query?
I am trying to insert data in a table. I am using a search query and then FetchRow in while condition to fetch the data in row and want to insert this row in a table directly. I have given the structure of table in this link. The code for insert values in table in while condition is here: require_once (ABSPATH . 'wp-admin/includes/upgrade.php'); $query = "(922=MIAMI), (131=2014-12-16+)"; $search = $rets->SearchQuery("Property", $class, $query, array("SystemName" => 1, 'Limit' => 1 )); if ($rets->NumRows($search) > 0) { $fields_order = $rets->SearchGetFields($search); $this_record = array(); while ($record = $rets->FetchRow($search)) { foreach ($fields_order as $fo) { echo $this_record[] = $record[$fo]; } $comma_fields_order = implode(",", $fields_order); $comma_record = implode(",", $this_record ); echo $dfsdf = "INSERT INTO rets_property_2 (".$comma_fields_order.") VALUES (" .$comma_record.")"; dbDelta($dfsdf); } } If I echo the insert query this is : INSERT INTO rets_property_2 (sysid,1,10,11,13,14,17,19,21,22,25,28,29,30,31,39,45,47,53,54,56,57,59,61,62,63,66,69,71,73,74,75,76,80,92,93,97,98,99,100,102,106,109,110,111,113,114,115,125,126,127,128,129,131,134,136,137,143,144,149,150,157,158,160,161,164,165,167,178,180,181,188,190,193,194,195,206,207,214,223,225,226,227,229,230,232,242,245,246,247,248,250,252,261,263,264,266,267,268,274,275,283,294,295,296,314,315,319,320,321,322,324,326,327,328,329,330,331,332,333,334,335,336,337,338,341,342,347,348,351,352,353,354,355,356,360,361,362,363,364,366,367,368,369,370,372,373,374,375,376,881,886,891,893,894,922,924,1088,1218,1223,1329,1333,1335,1337,1339,1358,1410,1462,1463,1464,1465,1473,1485,1486,1487,1488,1490) VALUES (305578689,Condo/Co-Op/Villa/Townhouse,33131,,,,3003,42,None,,4,,,,Entry Level,Miami Board of Realtors,0,,Cbs Construction,,,Electric Cooling,,Miami-Dade County,,,,ASIA CONDOMINIUM,,,,,,2008-06-12T14:19:47,5,2630,,,,,2,,1,Electric Heat,Condo,9,Yes,ASIA IS BRICKELL KEY ISLAND'S PREMIER LUXURY BLDG. W/ ONLY 123 UNITS, PRIVATE ELEVATORS, SPECTACULAR VIEWS AND MUCH MORE.,,,,,3813,2014-12-23T09:16:55,EWM 09,0648464,6000000,,Daysi Morey,,1,M1242705,,No,,Vacant,EWM Realty International,305-329-7600,,Maximum 20 Lbs,Yes,,0043,,Funding,Yes,5000000,T,EXOTIC LUXURY AND STRIKING DESIGN MAKES ASIA THE # 1 RESIDENCE FOR THE MOST DISCRIMINATING OWNER. SMART TECHNOLOGY, PRIVATE ELEVATORS, FLOOR TO CEILING WINDOWS, BREATHTAKING VIEWS OF BISCAYNE BAY, BAYSIDE, MIAMI RIVER AND MIAMI;S EXHUBERTANT SKYLINE. 12' CIELINGS,MARBLE BATHROOMS, GOURMET CHEF STYLE KITCHEN, LUXE BATH WITH FRENCH VANILLA IMPORTED MARBLE AND MUCH MORE MAKES THIS REMARKABLE RESIDENCE A SANCTUARY NESTLED IN BISCAYNE BAY. ALLOW 24 HOURS NOTICE FOR SHOWINGS.,,,6,6,,,0,,2014-01-24T10:02:22,Active-Available,BRICKELL KEY BLVD.,900,,,4663,Tax Reflects City & County Tax,New Construction,,,42,,0,2007,,None,Yes,Bay Front,2008,Under Construction,Bike/Jog Path,Elevator,0,No Approvals,,,ASIA CONDOMINIUM,,No,,,,Dishwasher,Dryer,Microwave,Electric Range,Refrigerator,Other Equipment/Appliances,Open Balcony,,30,Wood Floors,,Condominium,Elevator,Foyer Entry,Other Interior Features,0,All Amenities,Building Exterior,Cable Tv,1920,365,,,1,1 Assigned Space,2 Or More Spaces,,,0,Other Restrictions,,Elevator Secure,Garage Secured,Lobby Secured,,Condo 5+ Stories,34,Other,Condo,Corner Unit,High Rise,123,,Bay,,900 BRICKELL KEY BLVD. # 3003,,,,0,Miami,Florida,,,http://instatour.propertypanorama.com/instaview/mia/M1242705,2009-02-19T16:00:26,,,,ASIA CONDO UNIT 3003,1573.564,No HOPA,,,2389,No,No,No,No,900 BRICKELL KEY BLVD. 3003,Yes,) But nothing is being inserted in the table. Where I am wrong? Is there any other method to insert the whole row directly given by fetchrow into the table? Please show me right direction. I think the problem is with the data type, number and varchar. Then how can I format the insert query where data is coming from the array? I know my insert query is wrong. If I do try this INSERT INTO `rets_property_2` ( `sysid` , `1` ) VALUES ( 526252, 'dsfsdfsdf' ) this will work fine. But the question is How can I get the values from array if the value is string then 'somestringvalue' and if the value is integer then only integervalue and then wrapping them in a array?
$query = "(922=MIAMI), (131=2014-12-16+)"; $search = $rets->SearchQuery("Property", $class, $query, array("SystemName" => 1, 'Limit' => 5 )); if ($rets->NumRows($search) > 0) { $fields_order = $rets->SearchGetFields($search); while ($record = $rets->FetchRow($search)) { //var_dump($fields_order); foreach ($fields_order as $fo) { if( is_numeric($record[$fo])){ $valuesd[] = $record[$fo]; }else{ $onlyconsonants = str_replace("'", "", $record[$fo]); $valuesd[] = "'".$onlyconsonants."'"; } } $comma_fields_order = "`".implode("`,`", $fields_order)."`"; $valuestring = implode(",", $valuesd ); $wpdb->query("INSERT INTO rets_property_2 (".$comma_fields_order.") VALUES (".$valuestring.")"); unset($valuesd); $valuesd = array(); } /* end while */ } /* end if of number of row */
I would suggest using DBName column names instead of SystemName for your database table column names. I would also suggest using PDO to prepare/execute your statements. The below example should help you along: <?php $sysid = '1234' $property_1 = '1111 main' $stmt = $db->prepare("INSERT INTO table_name(`sysid`, `property_1`) VALUES( ?, ?)"); $stmt->execute(array($sysid, $property_1));
Function Errors in PHP Script
I've been wrestling with a really cool script someone gave me, trying to adapt it to my site. I'm getting closer, but I'm still getting two errors that have me puzzled. First: Warning: Invalid argument supplied for foreach()... This is the foreach statement: foreach ($Topic as $Topics) It follows a function: function generate_menu_items($PopTax, $Topics, $Current_Topic) I THINK the problem relates to the middle value in the function - $Topics. I don't understand how it's derived. My guess is it's supposed to be an array of all the possible topics (represented by $MyTopic in my database). But I'm not that familiar with functions, and I don't understand why he put the function and foreach BEFORE the database queries. (However, there is a more general DB query that establishes some of these values higher up the food chain.) Here's the second problem: Fatal error: Call to undefined function render_menu()... Can anyone tell me how and where I should define this function? Let me briefly explain what this script is all about. First imagine these URL's: MySite/topics/animal MySite/topics/animal-homes MySite/topics/animal-ecology MySite/topics/mammal-ecology MySite/topics/bird-ecology Two key values are associated with each URL - $PopTax (popular name) and $MyTopic. For the first three URL's, $PopTax = Animal, while the other two are Mammal and Bird. $MyTopic = Ecology for the last three rows. For the first two, $MyTopics = Introduction and Homes. The ID's for both values (Tax_ID and Topic_ID) are simply the first three letters of the name (e.g. Mam = Mammal, Eco = Ecology). Also, Life is the Parent of Animal, which is the Parent of Vertebrate, which is the Parent of Mammal. Now I'm just trying to pull it all together to create a little index in the sidebar. So if you visit MySite/topics/animal-ecology, you'd see a list of ALL the animal topics in the sidebar... Animals Animal Classification Animal Homes Animal Ecology As you can see there are some case and plural differences (animal vs Animals), though I don't think that really relates to the problems I'm having right no. But I'm not sure if my code just needs to be tweaked or if there's something grotesquely wrong with it. Something doesn't look right to me. Thanks for any tips. $Tax_ID = 'Mam'; // Mam represents Mammal $Current_Topic = 'Homes'; function generate_menu_items($PopTax, $Topics, $Current_Topic) { $menu_items = array(); foreach ($Topic as $Topics) { $url = "/topics/$PopTax[PopTax]-$Topic[MyTopic]"; $title = "$PopTax[PopTax] $Topic[MyTopic]"; $text = $Topic['MyTopic']; if ($Topic === 'People') { $url = "$PopTax[PopTax]-and-$Topic[MyTopic]"; $title = "$PopTax[PopTax] and $Topic[MyTopic]"; $text = "$PopTax[PopTax] & $Topic[MyTopic]"; } if ($Topic === 'Movement' && $PopTax['Parent'] == 'Ver' && $PopTax['PopTax'] != 'Human') { $url = "$PopTax[PopTax]-locomotion"; $title = "$PopTax[PopTax] Locomotion"; $text = "Locomotion"; } $menu_items[] = array( 'url' => strtolower($url), 'title' => ucwords($title), 'text' => ucfirst($text), 'active' => ($Topic['MyTopic'] === $Current_Topic) ); } return $menu_items; } function generate_menu_html($menu_items) { $list_items = array(); foreach ($menu_items as $item) { if ($item['active']) { $list_items[] = "<li><span class=\"active\">$item[text]</b></span></li>"; } else { $list_items[] = "<li>$item[text]</li>"; } } return '<ol>' . implode("\n", $list_items) . '</ol>'; } $stm = $pdo->prepare("SELECT T.Topic_ID, T.MyTopic FROM gz_topics T JOIN gz_topics_poptax TP ON TP.Topic_ID = T.Topic_ID WHERE TP.Tax_ID = :Tax_ID"); $stm->execute(array('Tax_ID' => $Tax_ID)); // Fetch all rows (topics) as an associative array $Topics = $stm->fetchAll(PDO::FETCH_ASSOC); // Get the DB row for the taxon we're dealing with $stm = $pdo->prepare("SELECT Tax.ID, Tax.PopTax, Tax.Parent FROM gz_poptax Tax WHERE Tax.ID = :Tax_ID"); $stm->execute(array('Tax_ID' => $Tax_ID)); // Fetch a single row, as the query should only return one row anyway $PopTax = $stm->fetch(PDO::FETCH_ASSOC); // Call our custom functions to generate the menu items, and render them as a HTML list $menu_items = generate_menu_items($PopTax, $Topics, $Current_Topic); $menu_html = render_menu($menu_items); // Output the list to screen echo $menu_html;
You want foreach ($Topics as $Topic). You are looping over each $Topic in $Topics is another way to think of it.
Retrieve only one row of comment
I have a site developed in codeigniter where I want to retrieve comment of a specific tee. I have a table tee like that: - id - user_id - name - created - modified And the table tee_comments like that: - id - user_id - tee_id - created - modified I have done this query: $this->db->select('*,tee.id as id,tee.created as created, tee_comments.id as tee_comments_id, tee_comments.created as tee_comments_created, tee_comments.modified as tee_comments_modified'); $this->db->from('tee'); $this->db->join('tee_comments', 'tee_comments.tee_id = tee.id','left outer'); $this->db->order_by("tee.created", "desc"); $query = $this->db->get(); With this query I retrieve two rows of tee because I have two comments in that tee. My goal is to retrieve only one row where inside there is an array of comment like: tee{ id, name, created, modified comment{ [0] id, tee_id, comment, created, modified [1] id, tee_id, comment, created, modified } } I have tried into the join: - left - right - left outer - right outer But doesn't solve the problem, is there a way to do that? Thanks
I love CodeIgniter! I use it constantly! You have 2 really simple options here: One way would be to use limit. $this->db->select('*,tee.id as id,tee.created as created, tee_comments.id as tee_comments_id, tee_comments.created as tee_comments_created, tee_comments.modified as tee_comments_modified'); $this->db->join('tee_comments', 'tee_comments.tee_id = tee.id','left outer'); $this->db->order_by("tee.created", "desc"); $query = $this->db->limit(1)->get('tee'); Another way is to get first item in results Array $query = $this->db->get(); $results = $query->result(); // gets return as an array $row = $results[0]; // will be first row in results array Keep in mind tho, $row will return as a object(stdClass) meaning you'll have to retrieve things from it like $row->column_name. A handy little snippet I like to use after a call is below. It makes the row Object's Array's instead. $results = $db->get('tee')->result(); // snippet comes after you have result array // snippet here foreach ($r as $k => $v) { $results[$k] = array(); foreach ($v as $kk => $vv) { $results[$k][$kk] = $vv != "NULL" ? trim($vv) : ""; } }
Use $this->db->limit(1) to retrieve a single record. According to the accepted answer on this question, you may need to put the limit statement before the select: $this->db->limit(1); $this->db->select('*,tee.id as id,tee.created as created, tee_comments.id as tee_comments_id, tee_comments.created as tee_comments_created, tee_comments.modified as tee_comments_modified'); $this->db->from('tee');
Option one: for ($i = 0; $i < count($records); $i++) { $data = $records[$i]; // work with date. if($i == 1) break; } Option two: just assign the first row to var. $row = $records['tee']['comment'][0];
Insert if not exists in DB and delete if not in an array
I have an array like this : $services = array( array("id" => "1", "desc" => "desc 1"), array("id" => "2", "desc" => "desc 2" ), ...... ); I want to insert those services in TABLE_SERVICE . each service is inserted if it doesnt exists in TABLE_SERVICE , and deleted it if it exists in TABLE_SERVICE but not in $services array. I could just delete all records in TABLE_SERVICE and then insert all $services elements , but that can be an issue with performance because i often have large set of data in both TABLE_SERVICE and $services . So is there an efficient way to do this ? Thanks.
If it was me I'd iterate over $services collecting ids: $ids = array(); foreach($services as $service) { $ids[] = $service['id']; } Then using PHP's join and the select NOT IN "DELETE FROM TABLE_SERVICE WHERE id NOT IN (" . join($ids,',') . ")" After that, iterate over the array again to insert/update using ON DUPLICATE KEY "INSERT INTO TABLE_SERVICE (id,desc) VALUES (?,?) ON DUPLICATE KEY UPDATE desc = ?" Since oracle doesn't have ON DUPLICATE KEY this stackoverflow question might help you with that last part.
My answer would be that there isn't really an efficient way to do this. I have thought about a merge, but to be efficient, you would still be better off first inserting it in a temporary table. Then you might as well just truncate table_service and then fill it again from your $service array. Even if Kristoffer's anwser could work, it might still be slower than a truncate insert. This is my php method to quickly insert a lot of records: The advantage of this is, that your insert statement will be parsed only once instead for each insert, which will improve the speed greatly. Sometimes by a factor 100 or so. $connection = oci_connect(<YOUR CONNECTION>); $sql = insert into table_service (id, var) values (:id, :var); // desc is a reserved word, cannot be a column name $parsed = oci_parse($connection, $sql); $binds = array(':id', ':var'); $sizes = array(6, 20); $data = $services; $errors = execute_multiple($binds, $sizes, $data); if ($errors > 0) // log or show else // feedback: full succes! function execute_multiple($binds, $sizes, $data, $commit = true) { $errorCount = 0; // first determine all binds once foreach ($binds as $i => $bind) { // ${trim($bind, ':')} example: :some_id -> $some_id oci_bind_by_name($parsed, $bind, ${trim($bind, ':')}, $sizes[$i]); } // Then loop over all rows and give the variables the new value for that row // This is because the variables remain binded! for ($row=0; $row<count($data); $row++) { foreach ($binds as $i => $bind) { $value = array_key_exists($i, $data[$row]) ? substr($data[$row][$i], 0, $sizes[$i]) : null; ${trim($bind, ':')} = trim($value); } if (! #oci_execute($this->parsed, OCI_DEFAULT)) // don't auto commit $errorCount++; } if ($commit) oci_commit($connection); return $errorCount; }