Multidimensional array PHP from MYSQL query - php

I have the following tables in MYSQL:
CommentTable with columns: comment, commenter, datecommented and postid
PostTable with columns: postid, dateposted
I perform this query in php
Select commentTable.comment, commentTable.commenter, commentTable.datecommented, shareTable.postid, shareTable.dateshared from shareTable Left Join commentTable on commentTable.postid = shareTable.postid where shareTable.postid IN ($postidarray) order by shareTable.dateshared desc
where $postid array is an array of post ids.
The problem I have is when i'm trying to sort the query result into a multidimensional array.
I would want to have a multidimensional array called comment which would like this
Comment{
[0] {
[0] => "Comment 1 from first key in $postidaray"
[1] => "Comment 2 from first key in $postidarray"
}
[1] {
[0] => "Comment 1 from second key in $postidarray"
} // assuming there is only one comment for the second key in $postidarray
[2]{
[0] => "Comment 1 from third key in $postidarray"
[1] => "Comment 2 from third key in $postidarray"
[2] => "Comment 3 from third key in $postidarray"
[3] => "Comment 4 from third key in $postidarray"
}
// assuming there are 4 comments for the third key in $postidarray
}
}
I'm doing this so that when I make a php echo I can loop out the comments relating to the specific post
For instance comment[0][1] would echo 'Comment 2 from first key in $postidarray'
Any help is appreciated.

You could do an ORDER BY shareTable.postId THEN BY shareTable.dateshared DESC
This would make all the rows with the same postId appear together so you could just check for a change of postId.
$i=-1;
$currentPostId=0;
$comment = array();
while($assoc = mysql_fetch_assoc($res)){
if($assoc['postId']!=$currentPostId){
$currentPostId = $assoc['postId'];
$i++;
}
$comment[$i][] = $res;
}
This should give you the result you want.
Alternately, If you use PDO, Use a prepared statement instead of using a single query with IN( ... )
$stmt = $pdo->prepare("Select ... shareTable.postid=? order by ShareTable.dateshared desc");
$comment = array();
$p = &$postIds[0];
$stmt->bindParam($p);
foreach($postIds as $p){
$stmt->execute();
$comment[] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

Related

LEFT JOIN only returns one row from right table

I have the following query;
"SELECT goals_challenges.*,
products_services.id as psid,
products_services.url,
products_services.feature_benefit
FROM goals_challenges
LEFT JOIN products_services ON goals_challenges.id = products_services.goal_challenge_id
WHERE persona_id = :persona_id"
Both tables have an 'id' column, hence the 'psid' alias.
However, despite there being two records that match the goal_challenge_id in the products_services table, only the first row is returned as part of the result set.
EDIT: Proper Data
goals_challenges
id persona_id title item_category solution
173 14 Lead Gen business challenge advertising
products_services
id goal_challenge_id url feature_benefit
1 173 www.testurl.com good for testing, mobile
2 173 www.google.com good for searching, well known
PHP code, including query;
public function findByPersonaId($persona_id)
{
try {
$this->dblayer->beginTransaction();
$stmt = $this->dblayer->prepare("SELECT goals_challenges.*, products_services.id as psid, products_services.url, products_services.feature_benefit from goals_challenges LEFT JOIN products_services ON goals_challenges.id = products_services.goal_challenge_id WHERE goals_challenges.persona_id = :persona_id");
$stmt->bindParam(':persona_id', $persona_id);
$stmt->execute();
$this->dblayer->commit();
$result_set = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$result_set[] = $this->mapObject($row);
}
return $result_set;
} catch (PDOException $e) {
$this->dblayer->rollBack();
echo $e->getMessage();
exit;
}
}
public function mapObject(array $row)
{
$entry = new GoalChallenge();
$entry->setId($row['id']);
$entry->setPersonaId($row['persona_id']);
$entry->setTitle($row['title']);
$entry->setItemCategory($row['item_category']);
$entry->setDescription($row['description']);
$entry->setSolution($row['solution']);
$entry->setProductService(new ProductService($row['psid'], $row['id'], $row['url'], explode(',', $row['feature_benefit'])));
$entry->SetResearchChecklist($row['research_checklist']);
$entry->setSubtopics($row['subtopics']);
$entry->setKeywords($row['keywords']);
$entry->setStatus($row['status']);
return $entry;
}
What I get returned
Array
(
[id] => 173
[persona_id] => 14
[title] => Lead Gen
[item_category] => Business Challenge
[solution] => Advertising
[product_service] =>
[research_checklist] => 0,0,0,0,0,0
[psid] => 1
[url] => www.google.com
[feature_benefit] => good for testing, mobile
)
EDIT: OK so I've worked out the result I am expecting is there, it's just not in the same goalChallenge object as the other - something in the PHP clearly - any ideas?
I get all the data from the goals_challenges table but only the first row (id 1) from the products_services table.
Is there a problem with my query? I have tried adding "GROUP BY goals_challenges.id" but it doesn't change the result.
Your query looks fine.
In ON condition , Column :- "goal_condition_id" has primary key or not.
Check , if both the columns have primary key.
Thanks
Aman
"SELECT gc.*,
ps.id as psid,
ps.url,
ps.feature_benefit
FROM product_services ps
LEFT JOIN goals_challenges gc ON gc.id = ps.goal_challenge_id
WHERE ps.persona_id = :persona_id"
Since your goal_challenges table has 1 row you are trying to find any proper match with product_services table. But only one row,
Select means distinguish rows for me under these conditions and
restrictions not duplicate rows for me.

grouping datas with same group

I'm trying to achieve to group Data by a column named 'groups'. I've been looking this post here Categorizing mysql data into seperate html tables?
This is also applicable in my case but the same groups get separated
This is what it looked like
_____________________________________
|_____________Group ZXY_______________|
| Month | Bet | Win |Payout|
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|_____Total_____|_______|______|______|
_____________________________________
|_____________Group ZXY_______________|
| Month | Bet | Win |Payout|
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|Name|Group|Desc| | | |
|_______________|_______|______|______|
|_____Total_____|_______|______|______|
As you can see the data returned are having the same group but got separated. Must be only using 1 table in this case
Summary of my idea
Group loop
add
<table><th>..</th></table>
tags inside the variable
Data fetch loop
add
<tr><td>..</td></tr>
tags inside the variable
Here's the code
$sql='SELECT DISTINCT `groups` FROM `kiosk_data` WHERE `groups` IS NOT NULL ORDER BY `groups` ASC';
$grpData='';
$grpHr[]=array();
//this is the code I used to fill im th contents of the dropdown box
$result = $conn->query($sql);
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if(!empty($row['groups']))
{
$selected = (isset($_GET['grp']) && $_GET['grp']==$row['groups'])?'selected="selected"':'';
$grpData.='<option value="'.$row['groups'].'"'.$selected.'>'.$row['groups'].'</option>';
$grpHr[]=$row['groups'];//took this opportunity to store the values of groups in grpHr[] Array
}
}
$sql = "SELECT COALESCE(kd.`kiosk_name`,'Total') AS 'Kiosk',
FORMAT(SUM(`casino_bets`),2) AS 'CBTotal', FORMAT(SUM(`bet_win`),2) AS 'BWTotal'
,FORMAT((`casino_bets`-`bet_win`)/`casino_bets`*100,2) AS 'Payout', groups FROM
`kiosk_data` kd LEFT JOIN `kiosk_status` ks ON kd.`kiosk_id`=ks.`kiosk_id` WHERE
`kiosk_name` IS NOT NULL AND `casino_bets` IS NOT NULL AND `bet_win` IS NOT NULL";
$result = $conn->prepare($sql);
$result ->execute();
foreach ($grpHr as $key => $value) {//iterate til the last group name
$key = $row['groups'];//I think I need to do this before entering the fetch loop
echo '<table><tr><td colspan="6">'.$row['groups'].'</td></tr><tr><th colspan="3">'.date("m",strtotime($row['date'])).'Month</th><th>Bet</th><th>Bet-Win</th><th>Payout %</th></tr>';
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
echo '<tr><td>'.$row['Kiosk'].'</td><td>'.$row['groups'].'</td><td>'.$row['city'].'</td><td>'.$row['CBTotal'].'</td><td>'.$row['BWTotal'].'</td><td>'.$row['Payout'].'</td></tr>';
}
}
Any other possible workaround for something better aside from my idea?
Assuming that your second query retrieves the needed data, please try the following version of your PHP code:
$sql='SELECT DISTINCT `groups` FROM `kiosk_data` WHERE `groups` IS NOT NULL ORDER BY `groups` ASC';
$grpData='';
$grpHr[]=array();
//this is the code I used to fill im th contents of the dropdown box
$result = $conn->query($sql);
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if(!empty($row['groups']))
{
$selected = (isset($_GET['grp']) && $_GET['grp']==$row['groups'])?'selected="selected"':'';
$grpData.='<option value="'.$row['groups'].'"'.$selected.'>'.$row['groups'].'</option>';
$grpHr[]=$row['groups'];//took this opportunity to store the values of groups in grpHr[] Array
}
}
$sql = "SELECT COALESCE(kd.`kiosk_name`,'Total') AS 'Kiosk',
FORMAT(SUM(`casino_bets`),2) AS 'CBTotal', FORMAT(SUM(`bet_win`),2) AS 'BWTotal'
,FORMAT((`casino_bets`-`bet_win`)/`casino_bets`*100,2) AS 'Payout', groups FROM
`kiosk_data` kd LEFT JOIN `kiosk_status` ks ON kd.`kiosk_id`=ks.`kiosk_id` WHERE
`kiosk_name` IS NOT NULL AND `casino_bets` IS NOT NULL AND `bet_win` IS NOT NULL";
$result = $conn->prepare($sql);
$result ->execute();
$grpsArr = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if( ! isset($grpsArr[$row['groups']])) {
$grpsArr[$row['groups']] = array();
}
$grpsArr[$row['groups']][] = $row;
}
foreach ($grpsArr as $grpName => $grpRowArray) {
echo '<table><tr><th colspan="6">'.$grpName.'</td></tr><tr><th colspan="3">'
.date("m",strtotime($row['date']))
.' Month</th><th>Bet</th><th>Bet-Win</th><th>Payout %</th></tr>';
foreach($grpRowArray as $grpRow) {
echo '<tr><td>'.$grpRow['Kiosk'].'</td><td>'.$grpRow['groups'].'</td><td>'.$grpRow['city'].'</td><td>'.$grpRow['CBTotal'].'</td><td>'.$grpRow['BWTotal'].'</td><td>'.$grpRow['Payout'].'</td></tr>';
}
echo '</table>';
}
What has been changed are the while / foreach loops. Below please find the explanation.
while loop
$grpsArr = array();
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
if( ! isset($grpsArr[$row['groups']])) {
$grpsArr[$row['groups']] = array();
}
$grpsArr[$row['groups']][] = $row;
}
This loop iterates through all of the rows returned by your last query, putting the data into $grpsArr nested array. The section :
if( ! isset($grpsArr[$row['groups']])) {
$grpsArr[$row['groups']] = array();
}
checks whether there has already been at least one row from the $row['groups'] group throughout the iteration - if there was no such row till now, sub array is created for $row['groups'] group name;
The line:
$grpsArr[$row['groups']][] = $row;
adds current iteration row to the subarray of the group indicated in $row['groups'].
After fetching the last record from the recordset, the $grpsArr array should look like:
grpsArr = array {
"group_1" => array {
array {
"Kiosk" => "KioskVal_1",
"groups" => "group_1",
"city" => "city_1",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
} ,
( ......... ) ,
array {
"Kiosk" => "KioskVal_31",
"groups" => "group_1",
"city" => "city_11",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
}
}
( .................... ),
"group_m" => array {
array {
"Kiosk" => "KioskVal_m",
"groups" => "group_m",
"city" => "city_m",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
} ,
( .................... ) ,
array {
"Kiosk" => "KioskVal_m2",
"groups" => "group_2",
"city" => "city_mm",
"CBTotal" => 123.45
"BWTotal" => ...
"Payout" => ...
}
}
}
foreach loop
foreach ($grpsArr as $grpName => $grpRowArray) {
echo '<table><tr><th colspan="6">'.$grpName.'</td></tr><tr><th colspan="3">'
.date("m",strtotime($row['date']))
.' Month</th><th>Bet</th><th>Bet-Win</th><th>Payout %</th></tr>';
foreach($grpRowArray as $grpRow) {
echo '<tr><td>'.$grpRow['Kiosk'].'</td><td>'.$grpRow['groups'].'</td><td>'.$grpRow['city'].'</td><td>'.$grpRow['CBTotal'].'</td><td>'.$grpRow['BWTotal'].'</td><td>'.$grpRow['Payout'].'</td></tr>';
}
echo '</table>';
}
The main loop foreach ($grpsArr as $grpName => $grpRowArray) iterates through the first level of $grpsArr table, getting the group name of currently processed group and then builds HTML table start tag with header row for this specific group.
Internal loop foreach($grpRowArray as $grpRow) iterates over the array containing rows that belong to the the currently processed group and builds HTML table row from the obtained data.
There is one problem: you used in your code .date("m",strtotime($row['date'])). for writing the proper date/time for the group. However there is no date field in the results of the last query - nevertheless I've put it also in my code.
This approach should give you one HTML table for each of the groups.
I hope it helps you some way.

MySql NOT IN many values from the mysql fetched result

I have 2 MySql queries which are interdependent.
My 'table1'
----------
id
----------
1
2
3
4
5
6
7
My First query
$sql1 = "SELECT * FROM table1 WHERE";// some condition which gives me id's 1,2,3
$res1=$obj->_executeQuery($sql1);
$res1=$obj->getAll($res1);
The result of this is giving me array
Array
(
[0] => Array
(
[id] => 1
..
..
)
[1] => Array
(
[id] => 2
..
..
)
[2] => Array
(
[id] => 3
..
..
)
)
I want to run another query on same 'table1', where not equal to list of ID's which i am getting from the first query.
My Second Query
$sql2 = "SELECT * FROM table1 WHERE id NOT IN (" . implode(',', $res1) . ")";
This is not showing me only one id i,e first. In above case i should get id's 4,5,6,7
Since implode will not give the desired value on multidimensional array so first you need to get the array of all id's to form one-dimensional array then use implode on the array of id's:
$id=array();
foreach ($res1 as $key=>$inner_array){
$id[]= $inner_array['id'];
}
you can use array_walk also here like this:
array_walk($res1,function($c) use (&$id) {$id[] = $c['id'];});
but i think the best one is array_map :
$id = array_map(function($i) {
return $i['id'];
}, $res1);
$sql2 = "SELECT * FROM table1 WHERE id NOT IN (" . implode(',', $id) . ")";
Note: when ever you are doing select please specify your column if you need few to select,unnecessarily selecting all will slow your sql processing.
suppose here:SELECT * FROM table1 WHERE, if you need only id then please select id only.
You have to change $res1, which is a two-dimensional array, into a one-dimensional array of IDs to be able to use implode:
$ids_from_first_query = array();
foreach($res1 as $result_row) {
$ids_from_first_query[] = $result_row['id'];
}
$ids_as_string = implode(',', $ids_from_first_query);
$sql2 = 'SELECT * FROM table1 WHERE id NOT IN(' . $ids_as_string . ')';
In the above code, $ids_as_string will look like this:
1,2,3
Thus it can be used in your MySQL query
Here you are getting two dimensional array so that's reason it is not working
while($each=mysql_fetch_array($res1))
{
$array[]=$each[id];
}
$imp=implode(",",$array);
$sql2 = "SELECT * FROM table1 WHERE id NOT IN (".$imp.")";
Try this it will works

Joining two mysql tables and populate an array in php

I have two tables
First table name is "Library"
ID Name
1 A
2 B
Second table name is "Books"
BID Book_Creater Book_Name
1 Variation1 Book1
1 Variation2 Book2
1 Variation3 Book3
2 Variation1 Book4
2 Variation2 Book5
The sql is
$sql = mysql_query("select library.ID,books.Book_Creater,books.Book_name from library,books where library.ID = books.BID;
Result is
ID Book_Creater Book_name
1 Variation1 Book1
1 Variation2 Book2
1 Variation3 Book3
2 Variation1 Book4
2 Variation2 Book5
Now I would like to create an array which should look like and this is where I am stuck.
array(
[1] => array(
[Variation1] => Book1
[Variation2] => Book2
[Variation3] => Book3
)
[2] => array(
[Variation1] => Book4
[Variation2] => Book5
)
)
Any suggestion will do great.
$res = array();
//for each result row
while($row = mysql_fetch_array($sql))
{
//add a row to the multi dimensional result array
//where the first key = id and the second key = Book_Creater
$res[$row['id']][$row['Book_Creater']] = $row['Book_name'];
}
print_r($res);
Simple way is to do a join as you currently do, and push them into an array as you loop around (possibly for neatness creating a new sub array explicitly when the ID as a key doesn't already exist).
Something like this:-
<?php
$store_array = array();
$sql = mysql_query("SELECT library.ID,books.Book_Creater,books.Book_name
FROM library
INNER JOIN books
ON library.ID = books.BID");
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
if (!array_key_exists($row['ID'], $store_array))
{
$store_array[$row['ID']] = array();
}
$store_array[$row['ID']][$row['Book_Creater']] = $row['Book_name']
}
print_r($store_array);
?>
You could also shuffle some effort onto the database and bring things back concatenated together. Then just split the results to put into the array:-
<?php
$store_array = array();
$sql = mysql_query("SELECT library.ID, GROUP_CONCAT(CONCAT_WS('#~#', books.Book_Creater,books.Book_name)) AS details
FROM library
INNER JOIN books
ON library.ID = books.BID
GROUP BY library.ID");
$result = mysql_query($sql);
while ($row = mysql_fetch_assoc($result))
{
$store_array[$row['ID']] = array();
$details = explode(',', $row['details']);
foreach($details as $detail)
{
$detail_line = explode('#~#', $row['detail']);
$store_array[$row['ID']][$detail_line[0]] = $detail_line[1];
}
}
print_r($store_array);
?>
Note that if you are doing this with real data you probably want to chose delimiters which are not going to appear in your data, and also that by default GROUP_CONCAT has a fairly limited max length.
Note also I have used mysql_* functions as that is what you seem to be using, but these are deprecated and probably shouldn't be used now.

How to get the result of a query with values in a array?

This is my function where i fetch my results from database
function Prof_Viewer($MemberId)
{
$query = $this->db->query("SELECT distinct(t1.dProfileId) as prof
FROM tbl_profile_viewer as t1
JOIN tbl_login as t2
WHERE t1.dProfileViwerId='$MemberId'");
if($query->num_rows > 0)
{
foreach($query->result() as $row)
{
echo $row->prof;//i am receiving many values here
$query1 = $this->db->query("SELECT distinct(t3.dUser_name),t2.dPath,t3.dCreatedDate
FROM tbl_login as t3
JOIN tbl_profile_viewer as t1,
tbl_member_details as t2
WHERE t3.dMember_Id = '$row->prof'
AND t2.dMember_Id ='$row->prof'");
}
return $query1->result_array();
}
}
As commented above i receive many values while echo the variable $row->prof;
say i have values such as 1 2 and 3.......
Even if i have these three values my 'query1' takes only the last value .so i have only one result i want the query to be executed for 1 and 2 also
how to Achieve that
You can just use PHP's explode() to convert your string into an array. For example:
<?php
$str = 'one|two|three|four';
// positive limit
print_r(explode('|', $str));
// gives you an array:
Array
(
[0] => one
[1] => two
[2] => three
[3] => four
)
?>
But I think you would be better off if you learned how to do JOIN's:
http://en.wikipedia.org/wiki/Join_(SQL)
I'm assuming you're using mysqli here.
Result_fetch_array() will do what you want
http://au2.php.net/manual/en/mysqli-result.fetch-array.php

Categories