Mysql return joined table as sub-array - php

I'm using my mysqli query as JSON output.
This is my query:
$sql = "SELECT p.*,comments.*,COUNT(comments.id) AS numComments FROM people AS p
LEFT JOIN comments ON comments.people_id = p.id
WHERE p.name LIKE '%".$data."%'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
$myArray[] = $row;
}
echo json_encode($myArray);
} else {
echo 0;
}
What I want to do, is to group all the person comments and place it under the person data. for example:
The desired output is that I will be able to access the comments not directly from the query, but from the person itself.
for example:
echo $person['comment'][0]['content']
Currently, I access it like any of the query data..
echo $person['content']
JSON OUTPUT:
As you can see, the person data and the comment data is mixed in the same array. I want the comments to have an array of their own.
Any ideas?
Edit: Seem like I have problem with the query. it returns only the first comment!

You need so-called eager loading for this task. It will involve two queries, but it will be way better than one.
You have to select your people first, then get people ids and query comments table for the comments. And finally you will have to combine the two arrays together.
I will use PDO as it will take 5 times less code to write, thanks to some neat PDO features.
$stmt = $conn->prepare("SELECT * FROM people WHERE name LIKE ?");
$stmt->execute(["%$data%"]);
$people = $stmt->fetchAll(PDO::FETCH_UNIQUE);
$ids = array_keys($people);
$in = str_repeat('?,', count($ids) - 1) . '?';
$stmt = $db->prepare("SELECT people_id, * FROM comments WHERE people_id IN ($in)");
$stmt->execute($ids);
$comments = $stmt->fetchAll(PDO::FETCH_GROUP);
foreach($people as $id=>$row)
{
$row['comments'] = $comments[$id];
$people[$id] = $row;
}

Related

How to use two different records from database?

I'm running a query to get results from the database. The results are then saved in an array. I want to know how can I use those results from array to get further results from the database in a single query. Or I'll have to use multiple queries?
$query2="SELECT officeName FROM office
WHERE parentOfficeID='$parent'";
$result2=mysqli_query($connect,$query2);
if(mysqli_num_rows($result2) != 0)
{
$results= array();
while ($row2 = mysqli_fetch_assoc($result2))
{
$results[]=$row2['officeName'];
}
}
The $results array saves the results. I want to use the officeName values individually. Is there any way I use single query? Or I'll have to process each value?
Hi If I understand your question then first you want to fetch some officeName and store them in array and then want to fetch some other info based on that officeName . You can use this one
<?php
$db = new mysqli('localhost','root','','databasename');
$result = mysqli_query($db,"SELECT officeName FROM office WHERE parentOfficeID='$parent'") or die(mysqli_error($db));
$officeName = array();
while($row = mysqli_fetch_assoc($result)){
$officeName[] = $row['officeName'];//store your office name in an array
}
$officeName= join("', '", $officeName);//The join() function returns a string from the elements of an array. It is an alias of the implode() function.
$sql = "SELECT * FROM office WHERE officeName IN ('$officeName')";// query with IN condition
$result1 = mysqli_query($db,$sql) or die(mysqli_error($db));
while($row1 = mysqli_fetch_assoc($result1)){
echo "<pre>";print_r($row1);
}
for more info more about join(). Please read http://www.w3schools.com/php/func_string_join.asp
for mysqli IN condition please read http://www.mysqltutorial.org/sql-in.aspx
To add to #Nyranith, you could also swap out your while statement and use
mysqli_fetch_all($result2, MYSQLI_ASSOC);
Which will return your values as an associative array without the need for you to loop through and build the array yourself.
It's been a really long time since I used mysqli, could need tweaking but here goes.
Here's a better way to go about the process itself:
Assume you have tables: Office and Staff and for some reason, you are binding the office to staff by the office name (bad juju)
$parent = 1;
$query2="SELECT o.officeName, s.name
FROM office AS o
INNER JOIN staff AS s ON o.officeName = s.officeName
WHERE o.parentOfficeID=?";
$stmt = $connect->prepare($query2);
$query = $stmt->bindParam($parent);
$exec = $stmt->execute();
$results2 = mysqli_fetch_all($exec, MYSQLI_ASSOC);
Now, do something with your result array
foreach($results2 as $key => $value) {
//loop through your results an do another query with them. Just like you queried the database to get these results.
}

Count rows in while loop

I am trying to while loop information into a SELECT statement, then COUNT the results. I have tried at least 10 different "solutions" and none works. I only get 0, 1, or nothing. Here's my most recent attempt:
$query35 = "SELECT * FROM movies WHERE userID = $memberID";
$result35 = $db->query($query35);
while ($row35 = $result35->fetchAll(PDO::FETCH_ASSOC)) {
$movie = $row35['movie'];
$query36 = "SELECT COUNT(*) AS similar FROM movies WHERE userID = '$profileID' && movie = '$movie'";
$result36 = $db->query($query36);
$row36->fetchObject;
$similar = $row36['similar'];
echo $similar;
}
$row36->fetchObject;
Seems null object, I think it should be
$row36 = $result36->fetchObject();
If all you are looking to do is count the number of times your loop is run per script execution, then it is fairly simple to do. See below:
$count = 0;
while($row35 = $result35->fetch(PDO::FETCH_ASSOC)){
//Do all your loop stuff.
$count++;
}
var_dump($count);
Important to note that your $count variable needs to be declared outside of your loop.
Also you either need to use fetchAll with a foreach loop, or use fetch with a while loop, but don't mix them.
Also a tip on good practice. Try to avoid as much as possible executing any kind of database querying with a loop, you can run into serious performance issues down the line as your loops get bigger.
Not sure what are you doing. But at least try:
$query35 = "SELECT * FROM movies WHERE userID = $memberID";
$result35 = $db->query($query35);
if ($row35 = $result35->fetchAll(PDO::FETCH_ASSOC))
foreach ($row35 as $row) {
print_r($row);
}
or maybe
$query35 = "SELECT * FROM movies WHERE userID = $memberID";
$result35 = $db->query($query35);
while ($row = $result35->fetch(PDO::FETCH_ASSOC)) {
print_r($row);
$movie = $row['movie'];
$query36 = "SELECT COUNT(*) AS similar FROM movies WHERE userID = '$profileID' && movie = '$movie'";
$result36 = $db->query($query36);
$obj = $result36->fetchObject();
$similar = $obj->similar;
echo $similar;
}

making a foreach loop inside an SQL query or do it dynamically via PHP?

I have 2 tables in my DB, Polyptychs and Illustrations. The PK of Polyptychs is FK in Illustrations.
What I want to do is:
SELECT polyptychID FROM Polyptychs
and subsequently, foreach ID returned I need all illustrations.
Via PHP the solution is something like this(using PDO sintax):
<?php
//create the connection with DB
$sql = "SELECT polyptychID, polyptych_image FROM Polyptychs";
$stmt = $this->DBH->query($sql);
$resultTmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
$final_result = array();
foreach($resultTmp as $val){
$id = $val['polyptychID'];
$final_result["$id"]["image"] = $val['polyptych_image'];
$sql2 = "SELECT * FROM Illustrations WHERE polyptychID = :polyID";
$stmt2 = $this->DBH->prepare($sql2);
$stmt2->execute(array('polyID' => $id));
$resultTmp2 = $stmt2->fetchAll(PDO::FETCH_ASSOC);
$final_result["$id"]["illustrations"] = $resultTmp2;
unset($id);
unset($sql2);
unset($stmt2);
unset($resultTmp2);
}
?>
Now $final_result contains all polyptychID as key of the array and its relative image and illustrations (if there's no error in the code).
What I want to know is if there is an easier way to get it, maybe doing it via SQL, and what is the best solution.
Thanks
You could run just one query using Inner Join:
SELECT P.polyptychID, polyptych_image, I.*
FROM Polyptychs P
INNER JOIN Illustrations I ON I.polyptychID = p.polyptychID
Now you loop the results adding them to the same array structure polyptychID as keys and illustrations as an array:
<?php
$sql = "SELECT P.polyptychID, polyptych_image, I.*
FROM Polyptychs P
INNER JOIN Illustrations I ON I.polyptychID = p.polyptychID";
$stmt = $this->DBH->query($sql);
$resultTmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
$final_result = array();
foreach($resultTmp as $val){
$id = $val['polyptychID'];
$final_result["$id"]["image"] = $val['polyptych_image'];
// I'm not sure what's the ID for Illustration table, so I'll assume `illustrationID`
$final_result["$id"]["illustrations"][$val["illustrationID"]] = $val;
unset($id);
}
?>
Here's what I'd do, if I were you:
SELECT p.polyptychID as ID,
p.polyptych_image as image,
i.*
FROM Polyptychs p
INNER JOIN Illustrations i
ON i.polyptychID = p.polyptychID
In light of your comment, check this handy graph to understand why an INNER JOIN is what I chose to use here:
Then, to format the array in the way you want it, just write this:
$formatted = array();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
$id = $row['ID'];
if (!isset($formatted[$id]))
{
$formatted[$id] = array(
'image' => $row['image'],
'illustrations' => array() //we'll set this in a minute
);
}
unset($row['ID'], $row['image']);//remove id & image values
$formatted[$id]['illustrations'][$row['illustrationsID']] = $row;//assign rest of result-set
}
Of course, if there are fields in the Illustrations called either ID or image, then you'd have to change the query to p.polyptychID AS p_ID or something. Just make sure the aliasses are unique and you'll be fine.
On the re-use of prepared statements, it seems to be something people tend to overlook, but you really can use the same prepared statements over and over. As luck would have it, in fact, I wrote an answer about this matter just this morning. I use some basic examples that might be applicable to your case, too. So if -for some reason- you can't do a join, you can simply write:
$stmt = $pdo->prepare(
'SELECT * FROM Illustrations WHERE polyptychID = :pId'
);
$baseStmt = $pdo->query(
'SELECT polyptychID, polyptych_image FROM Polyptychs'
);
$result = array()
while($row = $baseStmt->fetch(PDO::FETCH_ASSOC))
{
$result[$row['polyptychID']] = array(
'image' => $row['polyptych_image'],
'illustrations' => null
);
$stmt->execute( array(':pId' => $row['pId']));
$result[$row['polyptychID']]['illustrations'] = $stmt->fetchAll(PDO::FETCH_ASSOC);
}

SELECT FROM 2 different tables but related data

I have the following code
<?php
require_once('db_connection.php');
$return_arr = array();
$param = $_GET["term"];
$query = "SELECT *
FROM exp_weblog_data,exp_weblog_titles WHERE field_id_5
LIKE '%". $param ."%'
LIMIT 50";
$result = $mysqli->query($query) or die($mysqli->error.__LINE__);
/* Retrieve and store in array the results of the query.*/
while ($row = $result->fetch_assoc()) {
$row_array['jItemCode'] = $row['field_id_5'];
$row_array['jItemDesc'] = $row['title'];
/* $row_array['jItemWholesale'] = $row['itemWholesale'];
$row_array['jItemRetail'] = $row['itemRetail'];
$row_array['jItemPrice'] = $row['itemPrice'];
$row_array['jQtyOnHand'] = $row['qtyOnHand'];*/
array_push( $return_arr, $row_array );
}
$result->free_result();
$mysqli->close();
/* Toss back results as json encoded array. */
echo json_encode($return_arr);
I have two tables. "exp_weblog_data" and "exp_weblog_titles". Each table has "entry_id". When I use "field_id_5" from "exp_weblog_data" to start the autosuggest I need to pull additional information from the "exp_weblog_titles" table
This is for an auto complete query. I need to pull related data from "title" in another table in the same database can someone please help I know the problem lies with my query but I have tried all kinds of syntax with JOINS and UNIONS and LEFT JOINS what have you. Can someone please help me
I got it to work this way
$query = "SELECT field_id_5, exp_weblog_titles.title, field_id_57
FROM exp_weblog_data, exp_weblog_titles
WHERE exp_weblog_titles.entry_id = exp_weblog_data.entry_id AND field_id_5
LIKE '%". $param ."%'
LIMIT 10";
Thanks for all the help guys!
Use a JOIN clause. You can with one request get related data from 2 or more tables.
http://dev.mysql.com/doc/refman/5.0/en/join.html

Query goes in endless loop

The following goes into an endless loop, meaning it just constantly shows the same record over and over and over again.
<?php
while ($rowr = mysql_fetch_assoc(mysql_query("SELECT * FROM table1")) {
while($rowu = mysql_fetch_assoc(mysql_query("SELECT * FROM table2 WHERE id = '".$rowr['uid']."'"))){
while($rowc = mysql_fetch_assoc(mysql_query("SELECT * FROM table3 WHERE id = '".$rowr['cid']."'"))){
?>
<tr><td><?php echo $rowc['post']; ?></td><td><?php echo $rowu['username']; ?></td><td><font color="#FF0000">X</font></td></tr>
<?php
};
};
};
?>
Why does that happen and how can I fix it?
You are putting the mysql query in the while statement so every time it gets there it does the same query and shows the same first record, you are never advancing to the next record in the result set.
Personally I would combine all queries into one, but to show how you can solve your problem (the same applies to all loops):
$results = mysql_query("SELECT * FROM table3 WHERE id = '".$rowr['cid']."'");
while ($rowc = mysql_fetch_assoc($results))
{
// do stuff
}
Simply because the query gets executed again every time the loop condition is checked. That means you'll always get the same result unless something changes in the database in the meantime.
You need something like this:
<?php
$res1 = mysql_query("SELECT * FROM table1");
while ($rowr = mysql_fetch_assoc($res1)) {
$res2 = mysql_query("SELECT * FROM table2 WHERE id = '".$rowr['uid']."'");
while($rowu = mysql_fetch_assoc($res2)){
$res3 = mysql_query("SELECT * FROM table3 WHERE id = '".$rowr['cid']."'");
while($rowc = mysql_fetch_assoc($res3)){
?>
<tr><td><?php echo $rowc['post']; ?></td><td><?php echo $rowu['username']; ?></td><td><font color="#FF0000">X</font></td></tr>
<?php
}
}
}
?>
That's just to illustrate why it doesn't work. As others already noted, combining your queries into one using JOIN would be advisable.
Btw, you don't need a ; after a {} block.
Use joins and you can do it in one query.
Mysql Join
Join Tutorial
You're re-executing the queries on each loop iteration, restarting the results from scratch.
You want something like this instead:
$resultR = mysql_query("... table1");
while($rowR = mysql_fetch_assoc($resultR)) {
$resultU = mysql_query("... table2");
while($rowU = mysql_fetch_assoc($resultU)) {
etc...
}
}
Of course, this is a highly inefficient construct. You end up running count($rowR) * count($rowU) * count($rowC) queries. Why not reformulate it as a join?

Categories