Two MySQL result sets to a nested array - php

I'm having two tables of data "Item" and "Subsidiary" with the following structure:
ITEM
ItmCod
ItmName
SUBSIDIARY
ItmCodParent
ItmCodChild
I need to show a list of Items each with a list of its subsidiaries, like in this json:
{
"ItmCod":1,
"ItmName":"BogusItem1",
"Subsidiaries":
[
{
"ItmCodParent":1,
"ItmCodChild":15
},{
"ItmCodParent":1,
"ItmCodChild":16
}
]
},{
"ItmCod":2,
"ItmName":"BogusItem2",
"Subsidiaries":
[
{
"ItmCodParent":2,
"ItmCodChild":17
},{
"ItmCodParent":2,
"ItmCodChild":18
}
]
}
How can I add the second result set to the first one to have the nested as shown above. I have this code so far:
$sql = "SELECT ItmCod, ItmName FROM item";
$item_rows = array();
while($item_row = $database->fetch_array_assoc($item_result)){
$sub_sql = "SELECT ItmCodParent, ItmCodChild FROM subsidiary WHERE subsidiary.ItmCodParent = " . $item_row["ItmCod"];
$sub_result = $database->query($sub_sql);
$sub_rows = array();
while($sub_row = $database->fetch_array_assoc($sub_result)){
$sub_rows[] = $sub_row;
}
$item_rows[] = $item_row;
}
print json_encode($item_rows);
Thanks.

just above the line
$item_rows[] = $item_row;
simply add
$item_row['Subsidiaries']=$sub_rows;

I would do a single join query like this:
SELECT i.ItmCod AS ItmCod, i.ItmName AS ItmName, s.ItmCodChild AS ItmCodChild
FROM item AS i
INNER JOIN subsidiary AS s
ON i.ItmCod = s.ItmCodParent
Note I didn't select s.ItmCodParent as this is just redundant to i.ItmCod.
Then build the array like this:
$item_rows = array();
while($item_row = $database->fetch_array_assoc($item_result)){
$item_rows[(int)$item_row['ItmCod']]['ItmCod'] = $item_row['ItmCod'];
$item_rows[(int)$item_row['ItmCod']]['ItmName'] = $item_row['ItmCod'];
$sub_array = array(
'ItdCodParent' => $item_row['ItmCod'],
'ItmCodChild' => $item_row['ItmCodChild']
);
$item_rows[(int)$item_row['ItmCod']]['Subsidiaries'][] = $sub_array;
}
$item_rows = array_values($item_rows); // reset numerical indexes.
echo json_encode($item_rows);

I wouldn't attempt to solve this with two queries:
$sql = '
SELECT I.ItmCod, I.ItmName, S.ItmCodChild
FROM item I
LEFT JOIN subsidiary S ON (S.ItmCodParent = I.ItmCod)
';
// fetch $item_result with $sql
$item_rows = array();
while ($item_row = $database->fetch_array_assoc($item_result)) {
$cod = $item_row['ItmCod'];
if (!array_key_exists($cod, $item_rows)) {
$item_rows[$cod] = $item_row;
}
$item_rows[$cod]['Subsidiaries'] = array(
'ItmCodParent' => $cod,
'ItmCodChild' => $item_row['ItmCodChild'],
);
}
// array_values is because json_encode will keep the keys
// otherwise
print json_encode(array_values($item_rows));
That way, you aren't running an additional query for every single item row to get the subsidiaries (minimizing round-trip time, and letting the database do what it's good at).

Related

Why while loop does not showing result after first iteration inside while loop?

I'm trying to fetch the comments inside the while loop by newsfeed_id, but it does not showing any result after first iteration. I print_r dynamically generated query its working fine but result does not showing.
$NewsfeedRes = array();
$Newsfeed = "select * from `ws_newsfeed` where `nf_status` = 1";
$NewsfeedQuery = mysqli_query($this->connection,$Newsfeed);
while($rowNews = mysqli_fetch_assoc($NewsfeedQuery)){
$NewsfeedRes[] = $rowNews;
$PushComment = "SELECT cmt.`cmt_id`,cmt.`cmt_comment`,cmt.`date_added`,
us.`u_username`,us.`u_image`
FROM `ws_comments` AS cmt
LEFT JOIN `ws_user` AS us ON cmt.`u_id`=us.`u_id`
WHERE cmt.`cmt_target_id` = ".$rowNews['nf_id']."
AND cmt.`cmt_table_name`='ws_newsfeed'";
//echo $PushComment; This giving me correct query
$PushCommentQuery = mysqli_query($this->connection,$PushComment);
while($rowPComment = mysqli_fetch_assoc($PushCommentQuery)){
$NewsfeedRes['comments'] = $rowPComment;
}
}
$output = array(
'NewsfeedRes' => $NewsfeedRes,
);
echo json_encode($output, JSON_PRETTY_PRINT);
Can any one guide me where I'm wrong that i can fix the issue. I will appreciate. Thanks
Every time you loop through your fetch comment loop you are resetting the the value of $NewsfeedRes['comments']. You need to push $rowPComment into an array.
If you want $rowNews and comment to be in the same array try:
while($rowNews = mysqli_fetch_assoc($NewsfeedQuery)){
$PushComment = "SELECT cmt.`cmt_id`,cmt.`cmt_comment`,cmt.`date_added`,us.`u_username`,us.`u_image` FROM `ws_comments` AS cmt LEFT JOIN `ws_user` AS us ON cmt.`u_id`=us.`u_id` WHERE cmt.`cmt_target_id` = ".$rowNews['nf_id']." AND cmt.`cmt_table_name`='ws_newsfeed'";
//echo $PushComment; This giving me correct query
$PushCommentQuery = mysqli_query($this->connection,$PushComment);
while($rowPComment = mysqli_fetch_assoc($PushCommentQuery)){
$rowNews['comments'][] = $rowPComment;
}
$NewsfeedRes[] = $rowNews;
}
If you want a seperate array for comments and news feed try:
while($rowNews = mysqli_fetch_assoc($NewsfeedQuery)){
$NewsfeedRes["newsfeed"][] = $rowNews;
$PushComment = "SELECT cmt.`cmt_id`,cmt.`cmt_comment`,cmt.`date_added`,us.`u_username`,us.`u_image` FROM `ws_comments` AS cmt LEFT JOIN `ws_user` AS us ON cmt.`u_id`=us.`u_id` WHERE cmt.`cmt_target_id` = ".$rowNews['nf_id']." AND cmt.`cmt_table_name`='ws_newsfeed'";
//echo $PushComment; This giving me correct query
$PushCommentQuery = mysqli_query($this->connection,$PushComment);
while($rowPComment = mysqli_fetch_assoc($PushCommentQuery)){
$NewsfeedRes['comments'][] = $rowPComment;
}
}

PHP Array select result from other array

I have a sql table with some category, i get them in a array.. all fine but when i try to get data from another table foreach category, always return me for first category selected.
This is my code:
$gameguidecategoryes = array();
$gameguides = array();
$dbselectgameguidecategoryes = new DB_MSSQL;
$dbselectgameguidecategoryes->Database=$newweb_db;
$dbselectgameguidecategoryes->query("Select GameGuideCatNr,GameGuideCatName_$languageid as GameGuideCatName,GameGuideCatImage from GameGuide_Category where GameGuideCatVisible = 1 order by GameGuideCatOrder asc");
for($i=0;$i < $dbselectgameguidecategoryes->num_rows();++$i) {
if ($dbselectgameguidecategoryes->next_record()){
$GameGuideCatNr = $dbselectgameguidecategoryes->f('GameGuideCatNr');
$GameGuideCatName = $dbselectgameguidecategoryes->f('GameGuideCatName');
$GameGuideCatImage = $dbselectgameguidecategoryes->f('GameGuideCatImage');
}
$gameguidecategoryes_temp = array(
'ggcname' => $GameGuideCatName,
'ggcimg' => $GameGuideCatImage,
);
$gameguidecategoryes[$i] = $gameguidecategoryes_temp;
$dbselectgameguide = new DB_MSSQL;
$dbselectgameguide->Database=$newweb_db;
$dbselectgameguide->query("Select GameGuideID,GameGuideName_$languageid as GameGuideName from GameGuide_Content where GameGuideCat = $GameGuideCatNr and GameGuideVisible = 1 order by GameGuideOrder asc");
for($ii=0;$ii < $dbselectgameguide->num_rows();++$ii) {
if ($dbselectgameguide->next_record()){
$GameGuideID = $dbselectgameguide->f('GameGuideID');
$GameGuideName = $dbselectgameguide->f('GameGuideName');
}
$gameguides_temp = array(
'ggid' => $GameGuideID,
'ggn' => $GameGuideName,
);
$gameguides[$ii] = $gameguides_temp;
}
}
Why $gameguides return data only from first category?
Thank you
Your second loop keeps getting trashed by the first loop. e.g. Consider what happens:
You fetch your categories, and (let's pretend) there's 4 of them.
You store some information in $gameguidecategoryes[0]
You run the second query, get some content for category #0, say, 3 records
That gets stored in $gameguides[0], [1], [2]
Your outer loop ticks again, and you start on categoryes[1]
The inner loop ticks again, you get 4 records, and now you're storing them into the SAME again: $gameguides[0], [1], [2], [3], etc...
You've now trashed the data you fetched in the first loop, and will
do so for every category you fetch.
This code is very inefficient. You should learn how to use JOINs, and fetch into a single structure, e.g.
SELECT category.id, category.name, ...., content.id, content.name
FROM categories
LEFT JOIN content ON categories.id = content.category_id
ORDER BY ...
and then something like
$data = array();
while($row = fetch row from db) {
if (!isset($data[$row['category.id']]) {
$data[$row['category.id']] = array(
'name' => $row['category.name'],
'content' => array()
);
}
$data[$row['category.id']]['content'][] = array(
... save content data here
);
};
Better work on clean code
$gameguidecategoryes = $gameguides = $gameguidescategoryids = array();
$dbselectgameguidecategoryes = new DB_MSSQL;
$dbselectgameguidecategoryes->Database=$newweb_db;
$dbselectgameguidecategoryes->query("Select GameGuideCatNr,GameGuideCatName_$languageid as GameGuideCatName,GameGuideCatImage from GameGuide_Category where GameGuideCatVisible = 1 order by GameGuideCatOrder asc");
while ($dbselectgameguidecategoryes->next_record()) {
$gameguidescategoryids[] = $dbselectgameguidecategoryes->f('GameGuideCatNr');
$gameguidecategoryes[] = array(
'ggcname' => $dbselectgameguidecategoryes->f('GameGuideCatName'),
'ggcimg' => $dbselectgameguidecategoryes->f('GameGuideCatImage'),
);
}
if (count($gameguidescategoryids)) {
$dbselectgameguide = new DB_MSSQL;
$dbselectgameguide->Database=$newweb_db;
$dbselectgameguide->query("Select GameGuideID,GameGuideName_$languageid as GameGuideName from GameGuide_Content where GameGuideCat IN (".implode(',', $gameguidescategoryids).") and GameGuideVisible = 1 order by GameGuideOrder asc");
while ($dbselectgameguide->next_record()){
$gameguides[] = array(
'ggid' => $dbselectgameguide->f('GameGuideID'),
'ggn' => $dbselectgameguide->f('GameGuideName'),
);
}
}

MYSQL PHP API - Displaying & Fetching multiple rows within rows from another table

I'm creating an API for my mobile application. I'm developing this with PHP MYSQL and the Slim framework (which is largely irrelevant for this problem).
I'm trying to pull multiple "venues" from my mysql database, and retrieve multiple "venue_images" for each "venue". The database:
venues venue_images
------ ------------
id PK image_venue_id FK (to venues)
venue_name image_path
active
I then need to output the data in this format:
{
"completed_in":0.01068,
"returned":10,
"results":[
{
"venue_id":"1",
"venue_name":"NameHere",
"images": [
{
"image_path":"http://www.pathhere.com"
},
{
"image_path":"http://www.pathhere2.com"
}
]
}
]
}
So basically, the images are iterated multiple times for each venue.
My current code is:
$sql = "
SELECT
venues.id, venues.venue_name, venues.active,
venue_images.image_venue_id, venue_images.image_path
FROM
venues
LEFT JOIN
venue_images ON venue_images.image_venue_id = venues.id
WHERE
venues.active = 1
LIMIT 0, 10
";
$data = ORM::for_table('venues')->raw_query($sql, array())->find_many();
if($data) {
foreach ($data as $post) {
$results[] = array (
'venue_id' => $post->id,
'venue_name' => $post->venue_name,
'images' => $post->image_path
);
}
//Build full json
$time = round((microTimer() - START_TIME), 5);
$result = array(
'completed_in' => $time,
'returned' => count($results),
'results' => $results
);
//Print JSON
echo indent(stripslashes(json_encode($result)));
} else {
echo "Nothing found";
}
My current code works, however it produces this:
{
"completed_in":0.01068,
"returned":10,
"results":[
{
"venue_id":"1",
"venue_name":"The Bunker",
"images":"https://s3.amazonaws.com/barholla/venues/1352383950-qPXNShGR6ikoafj_n.jpg"
},
{
"venue_id":"1",
"venue_name":"The Bunker",
"images":"https://s3.amazonaws.com/barholla/venues/1352384236-RUfkGAWsCfAVdPm_n.jpg"
}
]
}
There's two images for "The Bunker". Instead of storing the images within the venue array, it's creating a duplicate row of "The Bunker", with the second image. Like I said earlier, I need to have multiple images iterating within each venue. Any help would be much appreciated! Thanks!
You want to use GROUP_CONCAT
Something like this (not 100% accurate probably :) )
$sql = "
SELECT
v.id, v.venue_name, v.active,
GROUP_CONCAT(i.image_path) as venue_image_string
FROM
venues v
LEFT JOIN
venue_images i ON i.image_venue_id = v.id
WHERE
v.active = 1
GROUP BY i.image_venue_id
LIMIT 0, 10
";
You may have to fiddle a little but should put you on the right track (note: provides venue_image_string as CSV)
Why can't you use multiple queries instead of..? Its faster and simple..!
$sql = "SELECT venues.id, venues.venue_name, venues.active FROM venues WHERE venues.active = 1 LIMIT 0, 10";
$data = ORM::for_table('venues')->raw_query($sql, array())->find_many();
if($data) {
foreach ($data as $post) {
$results[] = array ();
$sql = "SELECT image_path FROM venue_images WHERE image_venue_id = $post->id";
$images = ORM::for_table('venue_images')->raw_query($sql, array())->find_many();
$results[] = array (
'venue_id' => $post->id,
'venue_name' => $post->venue_name,
'images' => $images);
}
//Build full json
$time = round((microTimer() - START_TIME), 5);
$result = array(
'completed_in' => $time,
'returned' => count($results),
'results' => $results
);
//Print JSON
echo indent(stripslashes(json_encode($result)));
} else {
echo "Nothing found";
}

MySQL sorting with PHP

I'm trying to accomplish the following situation:
$mysql_query = "
SELECT *
FROM st_users
WHERE
`user_comp_supervisor_id` = '$team_supervisor' AND
`user_exempt_from_goals` = '0'
ORDER BY 'calculate_progress_percent()' ASC
";
I know that I can't accomplish ordering by a function in a MySQL statement, but I'm trying to figure out how to take all the returned records, and then order them in order of highest to lowest from a php function result. Any ideas would be greatly appreciated; I've been trying to wrap my head around this for a few hours now... :-(
function diy_calc_progress_percent($user_id,$period_id,$period_week_number)
{
$this->user_id = $user_id;
$this->period_id = $period_id;
$this->period_week_number = $period_week_number;
if ($this->period_week_number == 1)
{
$this->week_id = mysql_result( mysql_query(" SELECT `period_week_one` FROM `st_comp_periods` WHERE `period_id` = '$this->period_id' "),0 );
}
else if ($this->period_week_number == 2)
{
$this->week_id = mysql_result( mysql_query(" SELECT `period_week_two` FROM `st_comp_periods` WHERE `period_id` = '$this->period_id' "),0 );
}
else
{
echo "Week number not valid.";
exit();
}
$this->week_start_date = mysql_result( mysql_query(" SELECT `week_start_date` FROM `st_comp_weeks` WHERE `week_id` = '$this->week_id' "),0 );
$this->week_end_date = mysql_result( mysql_query(" SELECT `week_end_date` FROM `st_comp_weeks` WHERE `week_id` = '$this->week_id' "),0 );
$this->user_department = $this->user_info($this->user_id,"user_comp_department_id");
$this->user_week_diy_goal = mysql_result( mysql_query(" SELECT `goal_diy_department` FROM `st_comp_department_goals` WHERE `goal_department_id` = '$this->user_department' AND `goal_week_id` = '$this->week_id' "),0 );
$this->calc_totals_result = mysql_query("SELECT SUM(record_total_diy_revenue) AS user_week_total FROM `st_entered_records` WHERE `record_user_id` = '$this->user_id' AND `record_date` BETWEEN '$this->week_start_date' AND '$this->week_end_date'");
$this->calc_totals_row = mysql_fetch_assoc($this->calc_totals_result);
$this->user_week_total = $this->calc_totals_row['user_week_total'];
$this->user_week_one_percent = ($this->user_week_total / $this->user_week_diy_goal) * 100;
$this->user_week_one_percent = number_format( (float)$this->user_week_one_percent, 2, '.', '' );
return $this->user_week_one_percent;
}
You probably will have to do some array juggling.
First get all your entries FROM st_users into a first array (mysql_query)
Then you could run through that array, and for each entry you do the calculate_progress_percent() and build up a second array in which you could add the additional info ("user_progress_percent").
After this you can sort the new array ba your new info ("user_progress_percent").
And here is some quick and dirty code-suggestions – code is however not tested… of course…:)
First:
$mysql_query = "SELECT * FROM st_users
WHERE `user_comp_supervisor_id`='$team_supervisor' AND
`user_exempt_from_goals` = '0'";
Then something like this:
$i = 0;
while($tmp = mysql_fetch_array($mysql_query)) {
$my_second_array[$i]['user_id'] = $tmp['user_id'];
$user_id = $my_second_array[$i]['user_id'];
diy_calc_progress_percent($user_id,$period_id,$period_week_number);
$my_second_array[$i]['user_result'] = $diy_calc_progress_percent_result;
$i++;
}
And then sorting that second array should be possible as described here:
Sort Multi-dimensional Array by Value
…hope this helps at some point…

PHP json_encoding datas with parent and child categories

Iam trying with the json_encoding for about two hours but iam not getting the output as required. Actually this is a requirement for the mobile application developer who is asking in the format which i will explain here.The code below is what i have tried:
include_once("class_connection.php");
//Getting the Parent Category
$sqlStr = mysql_query("select catname , id from `category` where `parentid`='0'");
$jsonArray = array();
while ($fetchStr = mysql_fetch_assoc($sqlStr)) {
$jsonArray[] = array("ParentCategory" => $fetchStr["catname"]);
$id = $fetchStr['id'];
//Getting child categories from the above parent
$sqlChildStr = mysql_query("SELECT catname,id,parentid FROM `category` where `parentid`='$id'");
while ($fetchchildStr = mysql_fetch_assoc($sqlChildStr)) {
$jsonArray[] = array("ChildCategory" => $fetchchildStr["catname"]);
}
}
echo json_encode(array("JsonOutput" => $jsonArray)) . "<br />";
The Output is :
"JsonOutput":[{"ParentCategory":"Animals"},{"ChildCategory":"Bear"},{"ChildCategory":"Deer"},{"ChildCategory":"Dolphins"},
{"ParentCategory":"Art"},{"ChildCategory":"Hand Painting"},{"ChildCategory":"Painting"},{"ChildCategory":"3D"},{"ChildCategory":"Abstract"}]}
Here , in the above output the parent category array is empty without its child category array. I want to store all the child category array in its parent category array and finally i have to store both parent and child category into the JsonOutput array so i want the output as
"JsonOutput":[{
"ParentCategory":"Animals" : [{
{"ChildCategory":"Bear"},{"ChildCategory":"Deer"},{"ChildCategory":"Dolphins"}
]}
"ParentCategory":"Arts" : [{
{"ChildCategory":"Hand Painting"},{"ChildCategory":"Painting"},{"ChildCategory":"3D"}, {"ChildCategory":"Abstract"}
]}
]}
You probably need to do this (only the important bits are shown):
$jsonArray = array();
while ($parentCat = mysql_fetch_assoc($sqlStr)) {
$temp = array(
"ParentCategory" => $parentCat["catname"]
);
while ($childCat = mysql_fetch_assoc($sqlChildStr)) {
$temp["ChildCategory"][] = array(
"ChildCategory" => $childCat["catname"]
);
}
$jsonArray[] = $temp;
}
I used a temporary variable for storing and manipulating the parent category. This gets added to the main array at the end of loop.
Please use the following codes, give the index inside the while loop...
$jsonArray = {};
while ($fetchStr = mysql_fetch_assoc($sqlStr)) {
//$jsonArray[] = array("ParentCategory" => $fetchStr["catname"]);
$id = $fetchStr['id'];
//Getting child categories from the above parent
$sqlChildStr = mysql_query("SELECT catname,id,parentid FROM `category` where `parentid`='$id'");
while ($fetchchildStr = mysql_fetch_assoc($sqlChildStr)) {
$jsonArray["ParentCategory"][$fetchStr["catname"]] = array("ChildCategory" => $fetchchildStr["catname"]);
}
}
echo json_encode(array("JsonOutput" => $jsonArray)) . "<br />";

Categories