I have one loop for appending some strings to a variable. I need a best way of doing same. Currently I am pushing everything to an array then I implode it with comma. Is there any other best way of doing the same? Here is my code
$getDataProduct = "SELECT pm.*,crm.id sub_id, crm.name sub_name FROM `cp_reference_master` crm
LEFT JOIN product_master pm on crm.parent_id = pm.category
Where crm.mode = 'item_type_subcat' AND pm.id = ".$data['id'];
$logger->debug("Get Product From Product Master for ".$data['id']);
$logger->trace("Query: ".$getDataProduct);
$result = $db->func_query($getDataProduct);
//echo '<pre>'; print_r($result); echo '</pre>';
foreach($result as $details){
$result[0]['sub_ids'] = $details['sub_id'];
$result[0]['sub_names'] = $details['sub_name'];
}
In my query I am getting 3 or 4 rows. except sub_id and sub_name everything is same. I need to append this sub_id and sub_name and put it in first row of sub_id and sub_name
Not sure this is the correct place your problem is but I will give it a try.
foreach($result as $details){
$result_ids .= "," . $details['sub_id'];
$result_sub_names .= "," . $details['sub_name'];
}
This will create a comma first so you need to clear that with:
$result_sub_names = substr($result_sub_names,1);
$getDataProduct = "SELECT pm.*,crm.id sub_id, crm.name sub_name FROM `cp_reference_master` crm
LEFT JOIN product_master pm on crm.parent_id = pm.category
Where crm.mode = 'item_type_subcat' AND pm.id = ".$data['id'];
$logger->debug("Get Product From Product Master for ".$data['id']);
$logger->trace("Query: ".$getDataProduct);
$result = $db->func_query($getDataProduct);
$sub_ids = '';
$sub_names = '';
foreach($result as $details){
$sub_ids = $sub_ids.', '. $details['sub_id'];
$sub_names = $sub_names.', '. $details['sub_name'];
$result[0]['sub_ids'] = $details['sub_id'];
$result[0]['sub_names'] = $details['sub_name'];
}
Now Every thing int the $sub_ids and $sub_names, no need to implode array with comma.
Related
I'm getting the contents of a column which has contents stored as 3,2 then I'm using the explode function to separate them. The values separated are then used to query another table to bring names. Next I want to implode the results like burger, fries. But the results are not separated by the comma but are like burgerfries... This is what I have done:
$sql = "SELECT items FROM orders";
$result = mysqli_query($connection, $sql);
$array = mysqli_fetch_assoc($result);
$exploded = explode(",", $array['items']);
foreach ($exploded as $row){
$query = "SELECT food_name FROM foodlist WHERE food_id = $row";
$res = mysqli_query($connection, $query);
$arr = mysqli_fetch_assoc($res);
$imploded = implode(", ", $arr);
echo $imploded;
}
Because every $arr only contains one ingredient, so you're actually implode()ing just one element, echoing it, and then echoing other ingredients not separated by anything, so they show together.
You can add them to an array and then implode them:
$sql = "SELECT items FROM orders";
$result = mysqli_query($connection, $sql);
$array = mysqli_fetch_assoc($result);
$exploded = explode(",", $array['items']);
$ingredients = [];
foreach ($exploded as $row){
$query = "SELECT food_name FROM foodlist WHERE food_id = $row";
$res = mysqli_query($connection, $query);
$arr = mysqli_fetch_assoc($res);
$ingredients[] = $arr["food_name"];
}
echo implode(", ", $ingredients);
PRO TIP, it's a bad idea to have your fields separated by a comma like that in the database. You should normalize that field, have another table called ingredients and a pivot table called order_ingredient containing every ingredient a specific order has, then you can simply JOIN the ingredients by ID and get them all at once, instead of doing N+1 queries which will kill your performance fast.
The structure would look like this:
And the query something like
SELECT ingredient FROM orders o JOIN order_ingredient oi ON oi.order_id = o.id JOIN ingredients i ON oi.ingredient_id = i.id
which will return all your ingredients with just one query.
I see that you have already accepted an answer.
If you want to substantially reduce the number of queries you're executing, you could use the following single query to get a comma separated list of food items for all orders.
SELECT o.id, GROUP_CONCAT(f.name SEPARATOR ', ') AS food
FROM orders o
INNER JOIN food f ON FIND_IN_SET(f.id, o.items) > 0
GROUP BY o.id
Here's an SQL fiddle to demonstrate: http://sqlfiddle.com/#!9/b0004c/2
But the correct solution would be to normalize your database structure.
I am new to SQL and PHP. I have a requirement where the end user enters text in an HTML form, which I am storing in MySQL db. Later I query all the tables in the db which has the user data to obtain concatenated strings.
For a clearer understanding here is an image of my data and the desired result: Click for Image
Right now I am able to concatenate only one string based on a specific id with this query:
select group_concat(text order by T.did separator ' ') as TTT
from (
select l.dimgroupid as did, d.*, l.dimlevelid as id, l.dimlevelvalue,
concat(d.dimensiontext," ",l.dimlevelvalue) as text
from dimensionlevel l
join dimension d on d.dimensionid = l.dimid
join dimensiongroup g on g.groupid = l.dimgroupid) as T
where T.id=0;
which gives me the result
| TTT |
--------------------------------
| A 20 year old Man is Fresher |
I know I can use a loop on id, but the problem is the ids are not fixed.
Note: There can be "n" number of dimensions and levels.
Here is an SQL Fiddle of the data I am trying to query: SQL Fiddle
I have edited your query to get what you wanted..
select did as groupid, group_concat(text order by dimensionid separator ' ' ) as TTT
from (
select l.dimgroupid as did, d.*, l.dimlevelid as id, l.dimlevelvalue, concat(d.dimensiontext," ",l.dimlevelvalue) as text
from dimensionlevel l
join dimension d on d.dimensionid = l.dimid
join dimensiongroup g on g.groupid = l.dimgroupid
) as T
group by id;
I hope this helps you...
UPDATE :
using php..
$sql = "SELECT `dimensionid`, `dimensiontext`, `dimensiondescr` FROM `dimension`";
$dimensions = mysqli_fetch_all (mysqli_query($con, $sql));
$sql = "SELECT `dimlevelvalue` FROM `dimensionlevel` WHERE dimid IN (SELECT dimensionid FROM dimension WHERE dimensiondescr='age') ";
$ages = mysqli_fetch_all (mysqli_query($con, $sql));
$sql = "SELECT `dimlevelvalue` FROM `dimensionlevel` WHERE dimid IN (SELECT dimensionid FROM dimension WHERE dimensiondescr='sex') ";
$sexes = mysqli_fetch_all (mysqli_query($con, $sql));
$sql = "SELECT `dimlevelvalue` FROM `dimensionlevel` WHERE dimid IN (SELECT dimensionid FROM dimension WHERE dimensiondescr='experience') ";
$experiences = mysqli_fetch_all (mysqli_query($con, $sql));
foreach ($ages as $age) {
foreach ($sexes as $sex) {
foreach ($experiences as $exp) {
foreach ($dimensions as $dimension) {
$putage = "";
$putsex = "";
$putexp = "";
if($dimension[2]=="Age"){
$putage = $age[0];
}elseif($dimension[2]=="Sex"){
$putsex = $sex[0];
}elseif($dimension[2]=="Experience"){
$putexp = $exp[0];
}
echo $str = $dimension['1']." ".$putage.$putsex.$putexp." " ;
}
echo "<br>";
}
echo "<br>";
}
}
I got an array of ids that I want to use inside an IN statement (sql). However this can only be done when it is written correctly, for example: IN ('12', '13', '14')
How can I change an array of ids into that format? This means adding quotes around every number, and after every number surrounded by quotes a comma, except for the last one in the array.
My code:
$parent = "SELECT * FROM `web_categories` WHERE `parent_id` = 13 AND published = 1";
$parentcon = $conn->query($parent);
$parentcr = array();
while ($parentcr[] = $parentcon->fetch_array());
foreach($parentcr as $parentid){
if($parentid['id'] != ''){
$parentoverzicht .= "".$parentid['id']."";
}
}
I later want to use it like this:
$project = "SELECT * FROM `web_content` WHERE `catid` IN ('".$parentoverzicht."') AND state = 1";
Do this as a single query! SQL engines have all sorts of optimizations for working with tables, and doing the looping in your code is usually way more expensive.
The obvious query for your purposes would be:
SELECT wc.*
FROM web_content wc
WHERE wc.catid IN (SELECT cat.id
FROM web_categories cat
WHERE cat.parent_id = 13 AND cat.published = 1
) AND
wc.state = 1;
Use implode()..
<?php
$a1 = array("1","2","3");
$a2 = array("a");
$a3 = array();
echo "a1 is: '".implode("','",$a1)."'<br>";
echo "a2 is: '".implode("','",$a2)."'<br>";
echo "a3 is: '".implode("','",$a3)."'<br>";
?>
output->>>>>>>
a1 is: '1','2','3'
a2 is: 'a'
a3 is: ''
Have you tried to implode()?
Use ", " as glue. You will have to edit the string yourself to add a " at the beginning and end.
More info: http://php.net/manual/en/function.implode.php
Alternatively you can use single join query, like this.
SELECT con.* FROM `web_content` as con LEFT JOIN `web_categories` as cat
ON con.catid=cat.id WHERE cat.parent_id=13 AND published = 1
If the column's type in the DB is integer you do not actually need to quote the values, but in case it isn't, you can use array_map to quote every item in the array, then implode to join them with commas:
<?php
$ids = [1, 2, 3, 4, 5];
$sql = 'SELECT * FROM mytable WHERE id IN (?)';
$in_clause = array_map(function ($key) {
return "'$key'";
}, $ids);
$sql = str_replace('?', implode(',', $in_clause), $sql);
echo $sql;
Result:
SELECT * from mytable where id in ('1','2','3','4','5')
You can do something like this:
$ids = ['1','2','3','4']; //array of id's
$newArr = array(); //empty array..
foreach($ids as $ids)
{
$newArr[] = "'".$ids."'"; //push id into new array after adding single qoutes
}
$project = "SELECT * FROM `web_content` WHERE `catid` IN (".implode(',',$newArr).") AND state = 1"; /// implode new array with commaa.
echo $project;
This will give you :
SELECT * FROM `web_content` WHERE `catid` IN ('1','2','3','4') AND state = 1
Here this line $find_cond = str_replace('|',' ',$rem_exp); returns 225 and 245 number.
I want to get the records based on these two id number. But this below code returns the output repeatedly.
How do I properly put the while loop code inside a foreach?
foreach($arr_val as $key => $val)
{
$c_subsubtopic = str_replace('-','_',$subsubtopic);
$rem_exp = $val[$c_subsubtopic];
$find_cond = str_replace('|',' ',$rem_exp);
$sql = "SELECT a.item_id, a.item_name, a.item_url, b.value_url, b.value_name, b.value_id FROM ".TBL_CARSPEC_ITEMS." a, ".TBL_CARSPEC_VALUES." b WHERE a.item_id = b.item_id AND a.item_url = '".$subsubtopic."' AND value_id = '".$find_cond."' AND a.status = '1'";
while($r = mysql_fetch_array(mysql_query($sql)))
{
echo $r['value_name'];
}
}
The problem is that you are redoing the sql query at every iteration of the loop, thus resetting the results internal pointer, so you keep fetching the same array.
$res = mysql_query($sql)
should be on it's own line before the while loop, and then
while($r = msql_fetch_array($res))
This will properly increment through the $res list.
Try this and you are done
As you were getting may get multiple id in the string after replacing it so its better to use IN the where clause
foreach($arr_val as $key => $val)
{
$c_subsubtopic = str_replace('-','_',$subsubtopic);
$rem_exp = $val[$c_subsubtopic];
$find_cond = str_replace('|',',',$rem_exp);
$sql = "SELECT a.item_id, a.item_name, a.item_url, b.value_url, b.value_name, b.value_id FROM ".TBL_CARSPEC_ITEMS." a, ".TBL_CARSPEC_VALUES." b WHERE a.item_id = b.item_id AND a.item_url = '".$subsubtopic."' AND value_id IN('".$find_cond."') AND a.status = '1'";
while($r = mysql_fetch_array(mysql_query($sql)))
{
echo $r['value_name'];
}
}
I'm trying to enter all the course_code that have a score < 40 into array and echo it out somewhere. The print_r($carry_over) returns nothing!
$carry_over = array();
while ($row8 = mysql_fetch_assoc($query8)) {
if ($row8['score'] < 40) {
$carry_over[] = array('m.course_code' =>$row8['course_code']);
}
}
print_r($carry_over);
$query8 = mysql_query("SELECT m.score , m.course_code FROM maintable AS m
INNER JOIN students AS s ON m.matric_no = s.matric_no
INNER JOIN courses AS c ON m.course_code = c.course_code
WHERE m.matric_no = '".$matric_no."'
AND m.level = '".$level."'
AND m.score < 40"
) or die (mysql_error());
Your $query8 variable (the database query) should be defined before the while() function. Right now, the while() function iterates over 0 rows which, of course, results in an empty array.
$carry_over = array();
while ($row8 = mysql_fetch_array($query8))
{
$carry_over[] = $row8['course_code'];
}
Since you already check for rows where the score is less than 40 in your SELECT query, the check inside the while() function is redundant. You also missed a single-quote in front of course_code (it was previously a dot), and finally; adding an array inside the $carry_over array is unnecessary when you can just add the value directly to the first array.
2nd UPDATE
$matric_no = MAKE_SURE_TO_DEFINE_THIS;
$level = MAKE_SURE_TO_DEFINE_THIS;
// Fetch rows
$query8 = mysql_query("SELECT maintable.score, maintable.course_code, maintable.matric_no, maintable.level, students.matric_no, courses.course_code FROM maintable, students, courses WHERE (maintable.matric_no = '" . $matric_no . "' AND maintable.matric_no = students.matric_no) AND (maintable.course_code = courses.course_code) AND (maintable.level = '" . $level . "')");
$carry_over = array();
while ($row8 = mysql_fetch_array($query8))
{
// Save data to array
$carry_over[] = $row8['course_code'];
}
echo 'We found ' . mysql_num_rows($query8) . ' rows';
print_r($carry_over); // DEBUG
The array loop should be
If($row8['score'] < 40)
$carry_over[] = $row8['course_code'];
I think you might have to debug $row8 array first. to see what is inside or it probably got nothing at all