How to execute that in 1 query? - php

I have 2 tables customer and orders:
customers:
| custID | Name | Age |
|--------|-------|-----|
| 1 | Peter | 23 |
| 2 | Julie | 34 |
| 3 | Tom | 45 |
orders:
| custID | product | color |
|--------|---------|-------|
| 1 | shirt | blue |
| 1 | jacket | black |
| 2 | jacket | green |
| 3 | hat | grey |
| 3 | shirt | white |
I now want to get all customers and their orders, ordered as a list. So something like that:
Array
(
[0] => Array
(
[ID] => 1
[name] => Peter
[age] => 23
[orders] => Array
(
[0] => Array
(
[product] => shirt
[color] => blue
)
[1] => Array
(
[product] => jacket
[color] => black
)
)
)
[1] => Array
(
[ID] => 2
[name] => Julie
[age] => 34
[orders] => Array
(
[0] => Array
(
[product] => jacket
[color] => green
)
)
)
[2] => Array
(
[ID] => 3
[name] => Tom
[age] => 45
[orders] => Array
(
[0] => Array
(
[product] => hat
[color] => grey
)
[1] => Array
(
[product] => shirt
[color] => white
)
)
)
)
When I do:
SELECT name, age, product, color
FROM `customers`, `orders`
where `customers`.`id` = `orders`.id
group by name
I get:
| name | age | product | color |
|-------|-----|---------|-------|
| Peter | 23 | jacket | green |
| Julie | 34 | shirt | blue |
| Tom | 45 | hat | grey |
Is this even possible with only one query?

You could simply make the query below:
SELECT *
FROM customers
JOIN orders
USING custID
GROUP BY Name
ORDER BY custID ASC;

A couple of steps here...
First, you should run the following query:
SELECT
`customers`.`id`,
`customers`.`name`,
`customers`.`age`,
`orders`.`product`,
`orders`.`color`
FROM `customers`, `orders`
where `customers`.`id` = `orders`.`id`
order by `customers`.`id`
Which should give you de-normalized tabular data that looks something like this:
$array = array(
array("id" => 1, "name" => "Peter", "age" => 23, "product" => "shirt", "color" => "blue"),
array("id" => 1, "name" => "Peter", "age" => 23, "product" => "jacket", "color" => "black"),
array("id" => 2, "name" => "Julie", "age" => 34, "product" => "jacket", "color" => "green"),
array("id" => 3, "name" => "Tom", "age" => 45, "product" => "hat", "color" => "grey"),
array("id" => 3, "name" => "Tom", "age" => 45, "product" => "shirt", "color" => "white")
);
You can then transform the that data into your desired format as follows:
$transformed = array();
$i = 0;
while ($i < count($array)) {
$id = $array[$i]["id"];
$name = $array[$i]["name"];
$age = $array[$i]["age"];
$products = array();
while ($i < count($array) && $id == $array[$i]["id"]) {
array_push($products, array("product" => $array[$i]["product"], "color" => $array[$i]["color"]));
$i++;
}
array_push($transformed, array("id" => $id, "name" => $name, "age" => $age, "products" => $products));
}
http://sandbox.onlinephpfunctions.com/code/6fe856e1f71f699e84215b6f66d25589f71e255e

i think you should user INNER JOIN:
SELECT * FROM customers AS c INNER JOIN orders AS o ON c.custID = o.custID GROUP BY c.custID ORDER BY c.custID ASC;

There is no point in trying to achieve the desired outcome with single query. With the first query get the list of customers. Then perform a second query, which will load all the orders for the customers from the first query. And in a loop match orders to respective customers.
EDIT: something like this
$result = [];
$customers = $pdo->query("SELECT * FROM `customers`")->fetchAll();
foreach ($customers as $c) {
$result[$c['id']] = $c;
}
$orders = $pdo->query("SELECT * FROM `orders` WHERE `custID` IN (".implode(', ', array_keys($result).")");
foreach ($orders as $o) {
if (!isset($result[$o['custId']]['orders']))
$result[$o['custId']]['orders'] = [];
$result[$o['custId']]['orders'][] = $o;
}

Your sql SELECT name, age, product, color FROMcustomers,orderswherecustomers.id=orders.id group by name is fine, just add the customer id and order id also in the sql. Then, in PHP, as you iterate the result set, populate the customer info first (id, name, age) with customer id as the key and name, age as value as an array. Likewise, populate the order for that customer in the key 'orders' with the order id as key and value as an array (product, color).
Once you have the array populated, iterate over that array and keep putting things into a new array since the output you want is an array with sequential keys (0, 1, 2 etc) instead of customer id.
$initialList = array();
while($row = $result->fetch_assoc()) {
if(!array_key_exists($row['customer_id'], $initialList)) {
$initialList[$row['customer_id']] = array(
'name' => $row['name'],
'age' => $row['age'],
'orders' => array()
);
}
$initialList[$row['customer_id']]['orders'][] = array(
'product' => $row['product'],
'color' => $row['color']
);
}
$finalList = array();
foreach($initialList as $customerId => $customer) {
$customer['ID'] = $customerId;
$finalList[] = $customer;
}
//to print and check the array
print_r($finalList);

try this:
SELECT c.custID,c.name, c.age, group_concat(CONCAT_WS(':',o.product,o.color)SEPARATOR ',') as productos
FROM customers AS c
INNER JOIN orders AS o ON c.custID = o.custID
GROUP BY c.custID;
You just have to parse the products.
$array=array();
while($r = $res->fetch_assoc()) {
$id=$row['custID'];
$name=$row['name'];
$age=$row['age'];
$productos=$row['productos'];
$productsSeparats = explode(',',$productos);
$orders=array();
foreach ($productsSeparats as $value) {
$ar=explode(':',$value);
array_push($orders, array("product" => $ar[0], "color" => $ar[1]));
}
array_push($array, array("id" => $id, "name" => $name, "age" => $age, "orders" => $orders));
}

Related

How to create parent child relation in php

two tables Location and Routes. Location table contains following fields and values
id | name
1 | bangalore
2 | mumbai
3 | kolkatta
4 | delhi
Routes table contains following fields and values
id | source | desination
1 | 1 | 4
2 | 1 | 2
3 | 1 | 3
4 | 2 | 4
5 | 2 | 3
6 | 3 | 4
want to find all possible routes from source to destination like
bangalore-delhi
bangalore-mumbai-delhi
bangalore-mumbai-kolkatta-delhi
bangalore-kolkatta-delhi
please help me to achieve this result
Using your existing data from your two tables, you could LEFT JOIN columns source and destination from Routes meaning your INT values will match up to the Location.name column. Then make sure you order the data by source column for so it's easier to sort with PHP later on.
MySQL:
SELECT locStart.name as start, locFinish.name as finish FROM `routes`
LEFT JOIN location as locStart
ON routes.source = locStart.id
LEFT JOIN location as locFinish
ON routes.destination = locFinish.id
ORDER BY routes.source
Output:
array (
0 =>
array (
'start' => ' bangalore',
'finish' => 'delhi',
),
1 =>
array (
'start' => ' bangalore',
'finish' => 'mumbai',
),
2 =>
array (
'start' => ' bangalore',
'finish' => 'kolkatta',
),
//Etc....
Then add your DB results into multidimensional array using the Source name as the key.
$stmt = $pdo->query($query);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
$newArr;
foreach ($result as $v) {
$newArr[$v['start']][] = $v['finish'];
}
Output:
array (
' bangalore' =>
array (
0 => 'delhi',
1 => 'mumbai',
2 => 'kolkatta',
),
'mumbai' =>
array (
0 => 'delhi',
1 => 'kolkatta',
),
'kolkatta' =>
array (
0 => 'delhi',
),
)
For outputting the new array, you can use a recursive function:
function recurse($newArr, $key=NULL) {
if($key !== NULL) {
foreach ($newArr[$key] as $k=>$v) {
echo '<li>Destination: ' . $v . '</li>';
}
echo '</ul>';
} else {
foreach ($newArr as $k=>$v) {
echo 'Source: ' . $k . '<br><ul>';
recurse($newArr, $k);
}
}
}
Output:
Source: bangalore
Destination: delhi
Destination: mumbai
Destination: kolkatta
Source: mumbai
Destination: delhi
Destination: kolkatta
Source: kolkatta
Destination: delhi

Display Two tables data in Php

i have following tables
Author
id | author_name | author_detail | author_bio
books
id | author_id | book_name | book_detail
i want to display data in following way
Author Name ::
Author Detail ::
books :: 1.book1
2.book2
3.book3
4.book4
i have tried following query but didnt worked as per my requirement
select * from authors left join books on author.id=books.author_id
i have tried group concat but it gives books name with coma seperate.so i want to books detail in array
select author.author_name,author.author_detail,author.author_bio,group_concat(books.book_name) eft join books on author.id=books.author_id
i am expexting output like
Array
(
[0] => Array
(
[id] => 1
[name] => Norm
[books] => Array
(
[0] =>Array
(
[id] => 4
[book_name] => great wall
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
[1] =>Array
(
[id] => 6
[book_name] =>new book
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
)
)
[1] => Array
(
[id] => 2
[name] => Norm
[books] => Array
(
[0] =>Array
(
[id] => 2
[book_name] => amazing star
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
[1] =>Array
(
[id] => 3
[book_name] =>way of journy
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
)
)
i have checked this question also
displaying php mysql query result with one to many relationship
Can any one help me how to display data like above ?
thank you
Try this:
SELECT
A.id
A.author_name,
A.author_detail,
A.author_bio,
B.book_name,
B.created_at,
B.updated_at
FROM books AS B
LEFT JOIN author AS A
ON (A.id=B.author_id)
you will get result like this:
id | author_name | author_detail | author_bio | book_name
1 | ari | some detail | some bio | book_ari_1
1 | ari | some detail | some bio | book_ari_2
1 | ari | some detail | some bio | book_ari_3
2 | tester | some detail | some bio | book_tester_1
etc..
to make array as your expecting result you need to restructure your array result. i will asume your result array will be in $result variable
$new_result = array();
foreach ($result as $key => $value) {
if (empty($new_result[$value['id']]))
{
$new_result[$value['id']] = array(
'id' => $value['id'],
'name' => $value['name'],
'books' => array(
array(
'id' => $value['id'],
'book_name' => $value['book_name'],
'created_at' => $value['created_at'],
'updated_at' => $value['updated_at']
),
)
)
}
else
{
$new_result[$value['id']]['id'] = $value['id'];
$new_result[$value['id']]['name'] = $value['name'];
$new_result[$value['id']]['books'][] = array(
'id' => $value['id'],
'book_name' => $value['book_name'],
'created_at' => $value['created_at'],
'updated_at' => $value['updated_at']
);
}
}
the result will look like your expected. but the key number will be formated as id.
to reset key of $new_result as increment number you need to get only value use array_values() function
$new_result = array_values($new_result);
You could do it with your first query...but you'd have to check the author_id inside the record loop and show the author details only whenever the value changed (by comparing it with a value stored in a variable)...otherwise only show the book details.
So your code might (very roughly) look like this:
$query = "select whatever whatever...";
$records = $database->Execute($query);
foreach ($records as $fields) {
if ($fields['id'] != $previous_id) echo "Author ...";
echo "Book whatever whatever ...";
$previous_id = $fields['id'];
}
A more straightforward (although slightly longer) way would be to have a second query: a sub-query. And it would take place inside the loop through the results of the first (outer) query. So your outer query gets the authors and, after you show the author details, you have this separate query for books of the author...and you have a loop-within-the-outer-loop to show the details of each book.
So your code (very roughly) looks something like this:
$query = "select id, author_name, whatever from author";
$author_records = $database->Execute($query);
foreach ($author_records as $fields) {
echo "Author: {$fields['author_name']} whatever <br/>";
$subquery = "select whatever from books where id = whatever";
$book_records = $database->Execute($subquery);
foreach ($book_records as $otherfields) {
echo "Book whatever whatever";
}
}
you can do this in php no need to go in query itself but take both data in separate query i.e. books and author data
Remember i assumed $result as authors data and $result2 as books data
$item=array();
while($row=mysql_fetch_array($result))
{
$id=$row['id'];
$item[$id]['name']=$row['name'];
$item[$id]['id']=$row['id'];
$item[$id]['books']=array();
$temp=array();
while($row1=mysql_fetch_array($result2))
{
if($id==$row1['author_id'])
{
$temp['id']=$row1['id'];
$temp['book_name']=$row1['book_name'];
$temp['created_at']=$row1['created_at'];
$temp['updated_at']=$row1['updated_at'];
array_push($item['id']['books'],$temp);
}
}
}
Now here id is formatted as author's id. To get like array keys you can use array_values($item)

mysql - delete sql row where data not match with data in array

Please can I have some help on this. I'm trying to delete SQL row in a table that are not match the data in an array.
SQL Table:
| id | Name | No
------------------
| 1 | john | 14
| 2 | rui | 156
| 3 | ted | 148
| 4 | alex | 123
| 5 | depay | 56
Array:
Array
(
[0] => Array
(
[name] => john
[no] => 14
)
[1] => Array
(
[name] => ted
[no] => 148
)
[2] => Array
(
[name] => depay
[no] => 56
)
)
This may help you
[akshay#localhost tmp]$ cat test.php
<?php
$array = array (
array (
'name' => 'john',
'no' => '14'
),
array (
'name' => 'ted',
'no' => '148'
),
array (
'name' => 'depay',
'no' => '56'
)
);
$table = "some_table";
$sql = "DELETE FROM ".$table." WHERE (NAME,NO) NOT IN (". implode(",",array_map(function($_){ return sprintf("('%s',%d)",$_['name'],$_['no']);},$array)).")";
print $sql."\n";
?>
Output
[akshay#localhost tmp]$ php test.php
DELETE FROM some_table WHERE (NAME,NO) NOT IN (('john',14),('ted',148),('depay',56))
It would be much easier if you can return "id" aka primary key of the table as array. In that case you can just grab those ids and during delete operation exclude those from the equation.
$selectQ = 'select id from table_name'; // and no>10
$result = mysql_result($selectQ);
$ids = array();
while ($info = mysql_fetch_assoc($result)) {
$ids[] = $info['id'];
}
if($ids) {
$deleteQ = 'delete from table_name where id not in ('.implode(",", array_values($ids)).')';
mysql_query($deleteQ);
}
P.S : During select query make sure to include logic for finding those users. For example, who's "no" is greater than X.Otherwise this query in default will return all ids and eventually nothing will be deleted.

PHP Display an array in table format

I have an array like below, I need to display that array into table. I have tried the function using PHP but it getting rows and cells value, I need three type of values:
Rows name
Columns name
name for the corresponding row and column
Note : I have convert the below array1 into array 2
Array 1 :
Array
(
[0] => Array ([id] => 1[rows] => R1[columns] => c1[name] => 1)
[1] => Array([id] => 2[rows] => R1[columns] => c2[name] => 2)
[2] => Array([id] => 3[rows] => R1[columns] => c3[name] => 3)
[3] => Array([id] => 4[rows] => R2[columns] => c1 [name] => 1)
[4] => Array([id] => 5[rows] => R2[columns] => c2[name] => 2)
[5] => Array([id] => 6[rows] => R2[columns] => c3[name] => 3)
)
Array 2 :
Array
(
[0] => Array([0] => R1[1] => c1[2] => 1)
[1] => Array([0] => R1[1] => c2[2] => 2)
[2] => Array([0] => R1[1] => c3[2] => 3)
[3] => Array([0] => R2[1] => c1[2] => 1)
[4] => Array([0] => R2[1] => c2[2] => 2)
[5] => Array([0] => R2[1] => c3[2] => 3)
)
Table :
id | row | column | value
--------------------------
1 | r1 | c1 | 1
2 | r1 | c2 | 2
3 | r1 | c3 | 3
4 | r2 | c1 | 1
5 | r2 | c2 | 2
6 | r2 | c3 | 3
Function : This function convert the array2 into table
function convetTable($array) {
$rows = array();
$rows[0] = array();
foreach ($array as $column) {
if (!in_array($column[1],$rows[0])) {
$rows[0][] = $column[1];
}
}
$count = count($rows[0]);
foreach ($array as $row) {
$rowTtl = $row[0];
$rowQty = $row[1];
$rowVal = $row[2];
if (!isset($rows[$rowTtl])) $rows[$rowTtl] = array_pad(array(),$count,0);
$rows[$rowTtl][array_search($rowQty,$rows[0])] = $rowVal;
}
return $rows;
}
$table = convetTable($array2);
HTML :
{foreach from=$table item=key key=foo}
<tr class="prototype" id="first_row">
<td>Remove Row
<td><input type="text" name="rows[]" value="{$foo}" class="number" /></td>
{foreach from=$key item=cell}
<td align="center"><input type="text" name="cols[]" value="{$cell}" class="id number" /></td>
{/foreach}
</tr>
{/foreach}
Expected OutPut
0 C1 C2 C3
R1 1 2 3
R2 1 2 3
PS : here c1,c2,c3,1,2,3 are $cell value.
What I try to display $row,$col,$name, but here I'm getting $row and $cell only.
I need another value name for the corresponding row and column.
try this..
$count = count($array); //this will give you the count of elements of your array...
echo "<table border="1"><tr><th>ID</th><th>ROWS</th><th>COLUMNS</th><th>NAMES</th></tr>";
for($i=1;$i<=$count;$i++) //loop through the array..
{
echo "<tr><td>$i</td><td>".$array[$i][0]."</td><td>".$array[$i][1]."</td><td>".$array[$i][2]."</td></tr>";
}
echo "</table>";
Please note this code is to show you how to simplify your massiave code... may be you will need to edit this code to get the desired output...

PHP fill the missing values with empty values in an array

I have the array like
array(
[0] => array(
[a] => r1,
[b] => c1,
[c] => d1,
),
[1] => array(
[a] => r1,
[b] => c1,
[c] => d2,
),
[2] => array(
[a] => r1,
[b] => c1,
[c] => d3,
),
[3] => array(
[a] => r1,
[b] => c2,
[c] => d1,
),
[4] => array(
[a] => r1,
[b] => c2,
[c] => d3,
),
[5] => array(
[a] => r1,
[b] => c3,
[c] => d1,
)
)
Currently I am getting the output like
-------------------------------------
| C1,D1 | C1,D2 | C1,D3 |
-------------------------------------
| C2,D2 | C3,D1 | - |
-------------------------------------
| - | - | - |
-------------------------------------
But I need the output must be displayed by 3x3 matrix Like
-------------------------------------
| C1,D1 | C1,D2 | C1,D3 |
-------------------------------------
| - | C2,D2 | - |
-------------------------------------
| C3,D1 | - | - |
-------------------------------------
Please help me to fill the missing values with empty values
My code :
for($i=1; $i<=3; $i++){
for($j=1; $j<=3; $j++){
for($r=0; $r<9; $r++){
if(isset($rows[$r]) && $rows[$r]['b'] == 'C'.$i && $rows[$r]['c'] == 'D'.$j) {
//Store data to array
$data[] = array(
'a' => $rows[$r]['a'],
'b' => $rows[$r]['b'],
'c' => $rows[$r]['c']
);
}
}
}
}
Option => Fill the array with empty values then fill in the values you got.
Option => Remember which index positions you fill and then fill the rest by excluding the ones u filled.
Number 1 is easier.
Number 2 has better performance.
You can use array_fill
or do a loop through the array:
for( $i = 0 ; $i < MAX ; $i++ )
arr[i] = ""; // fill with whatever value you like

Categories