I'm trying to do something with PHP & MySQL that I just cannot get my head around.
I have a table that takes the following structure (they are two tables but will act as one when they are joined in the SQL query):
id | brand | model
1 | brand1 | model1
2 | brand1 | model2
3 | brand1 | model3
4 | brand2 | modelA
I've been able to get PHP to output the following fine:
brand1 model1
brand1 model2
brand1 model3
brand2 modelA
What I'd really like to be able to do is output it as:
Brand1
Model1
Model2
Model3
Brand2
ModelA
Anyone got any ideas?
This is my current code:
<?php
$result = mysql_query("SELECT cameras.cameraid, cameras.model, brands.brand FROM cameras JOIN brands ON cameras.brandid=brands.brandid WHERE cameras.categoryid='$cat' ORDER BY brands.brand ASC, cameras.level ASC")or die(mysql_error());
while($row = mysql_fetch_array($result))
{
echo "<li><a href='camera.php?id=". $row['cameraid'] . "'>" . $row['brand'] . " " . $row['model'] . "</a></li>";
}
?>
What you're looking for is a two-dimensional array with a nested foreach-loop. This will allow you to have an array that looks like this
Array (
[brand1] => Array (
[1] => model1
[2] => model2
[3] => model3
)
[brand2] => Array (
[4] => modelA
[5] => modelB
[6] => modelC
)
)
We use this to our advantage when we are later echoing out the models as a list of each brand. The first array will contain all the brands, while each brand is a array of its own - creating the two dimensional array, which contains all the models (and the product IDs as the key for the elements in that array).
Put each of your elements into an array in your while($row = mysql_fetch_array($result))-loop, and use the nested foreach-loop to echo them out.
while ($row = mysql_fetch_array($result)) {
// Here we fetch all the results, and put it into a two-dimentional array
// with keys as brandname and the ID of the product
$brands[$row['brand']][$row['cameraid']] = $row['model'];
}
// Then we echo them all out in a list!
foreach ($brands as $key=>$brand) {
// The $key is the name of the brand
echo $key."<ul>";
foreach ($brand as $id=>$model) {
// The $id is the ID of the camera in the table
// The $model is the model-name itself
echo "<li><a href='camera.php?id=".$id."'>".$model."</a></li>";
}
echo "</ul>";
}
Furthermore, it's deprecated and not recommended, to use mysql_* functions, you should consider moving onto mysqli_* or PDO for better functionality, continuous support and better security.
You should try something like this. It is using multidimensional arrays to group items.
<?php
$result = mysql_query("SELECT cameras.cameraid, cameras.model, brands.brand FROM cameras JOIN brands ON cameras.brandid=brands.brandid WHERE cameras.categoryid='$cat' ORDER BY brands.brand ASC, cameras.level ASC")or die(mysql_error());
$brands = array();
while($row = mysql_fetch_array($result))
{
$brands[$row['brand']][] = array($row['model'], $row['cameraid']);
echo "<li><a href='camera.php?id=". $row['cameraid'] . "'>" . $row['brand'] . " " . $row['model'] . "</a></li>";
}
foreach($brands as $brand => $data){
echo $brand . "<br>";
foreach($data as $item){
echo "<li><a href='camera.php?id=" . $item[1] . "'>" . $item[0] . "</a></li>";
}
}
?>
below is the code for grid using table It will give you and idea how to achieve your task
$sql = mysql_query("SELECT id, member_name FROM member_table ORDER BY id DESC LIMIT 15");
$i = 0;
// Establish the output variable
$dyn_table = '<table border="1" cellpadding="10">';
while($row = mysql_fetch_array($sql)){
$id = $row["id"];
$member_name = $row["member_name"];
if ($i % 3 == 0) { // if $i is divisible by our target number (in this case "3")
$dyn_table .= '<tr><td>' . $member_name . '</td>';
} else {
$dyn_table .= '<td>' . $member_name . '</td>';
}
$i++;
}
$dyn_table .= '</tr></table>';
line by line explanation of this code is in the link below
Array gird output tutorial will give you some Idea try to use this for your won scnario
Array Grid output tutorial well explained video
Related
I have a table called Orders with 2 attributes: id_order and id_product.
In this table, I save the list of the products bought adding this to a single id of order, something like this
id_order - id_product
1 - 1
1 - 2
1 - 5
1 - 6
2 - 4
2 - 8
2 - 14
3 - 1
I want to show this record in a table, BUT only showing one(1) time the id of order.
<?php
include "con.php";
$sql = "SELECT DISTINCT a.id_order , b.id_product FROM orders a JOIN orders b ON a.id_order=b.id_order";
$sentence1 = $con->prepare($sql);
$sentence1->execute();
$sentence1->bind_result($id, $product);
?>
<html>
<body>
<table border="3">
<tr>
<td>ID of order</td>
<td>ID of products from this order</td>
</tr>
<?php
while ($sentence1->fetch()) {
echo "<tr>";
echo "<td>" . $id . "</td>";
echo "<td>" . $product . "</td>";
echo "</tr>";
}
$sentence1->close();
?>
The problem is this SQL show repeatable times the number of id_order I want something like this:
id_order - id_product
1 - 1
- 2
- 5
- 6
____________
2 - 4
- 8
- 14
____________
3 - 1
The result I want is:
Another design:
While iterating over your result set in PHP, you can keep track of whether you encounter a new id value. If so, then display it in a table cell, otherwise do not display it.
$id_prev = NULL;
while ($sentencie->fetch()) {
echo "<tr>";
if ($id != $id_prev) {
echo "<td>" . $id . "</td>";
$id_prev = $id;
}
else {
echo "<td></td>"; // you could try adding spaces here for padding
}
echo "<td>" . $product . "</td>";
echo "</tr>";
}
As for the separator line, this is probably something which should be handled in your CSS/HTML layer.
Update:
It looks like your new requirement is to have the id table cells span multiple product rows. One option would be to use the rowspan attribute of the table cell. The trick here is that we need to iterate across an entire id before we know how many products there are.
$id_prev = NULL;
$products = array();
function displayRow($id, $products) {
for ($x = 0; $x < count($products); $x++) {
echo "<tr>";
if ($x == 0) {
echo "<td rowspan=\"" . count($products) . "\">" . $id . "</td>";
}
echo "<td>" . $products[$x] . "</td>";
echo "</tr>";
}
}
while ($sentencie->fetch()) {
if ($id != $id_prev) {
displayRow($id, $products);
$products = array();
$id_prev = $id;
}
array_push($products, $product);
}
// DON'T forget to call displayRow() one last time, to cover the final id
// appearing in your result set
displayRow($id_prev, $products);
Here sql command .
$sql = "SELECT DISTINCT id_order, GROUP_CONCAT(DISTINCT id_product ORDER BY id_product) AS child_id_list FROM orders group by id_order ORDER BY id_order";
$sentence1 = $con->prepare($sql);
$sentence1->execute();
$sentence1->bind_result($id, $product);
I have two databases and tables in each. Am reading the renewal_date of DB1 table 1 and taking the renewal_date of the current month and domain_name for that record.
then am trying to retrieve the d_due_date from DB2 table2 for the domain_name selected from DB1 table1.
then i need to display domain_name, renewal_date,d_due_date in one table.
I can do this by joining the database with INNER JOIN.
what i need is to write separate select queries and display.
$sql = "select domain_name from table1 where MONTH(renewal_date) = '06'";
$result = mysqli_query($link_id,$sql);
if(!$result) die(sql_error());
$DoNM= Array();
$sql1= "select d_due_date from domains where d_domain IN ('abc.com','akaaasa.com')";
$result1 = mysqli_query($link_id1,$sql1);
if(!$result1) die(sql_error());
$DoNM1= Array();
echo '<table>';
while(($row1 = mysqli_fetch_array($result1,MYSQL_ASSOC))&&($row = mysqli_fetch_array($result,MYSQL_ASSOC))){
echo "<tr>";
echo "<td>" .$DoNM[]= $row['domain_name'] . "</td>";
echo "<td>" .$DoNM[]= $row['renewal_date'] . "</td>";
echo "<td>" .$DoNM1[]= $row1['d_due_date'] . "</td>";
echo "</tr>";
}
echo '</table><br />';
I have hardcoded the domain name in $sql1. what I want is to get that from $sql. how can I do that.
So all you need to do is process through the first query results and build the array, then convert the contents of the array to a comma delimited list
$sql = "select domain_name, renewal_date
from table1
where MONTH(renewal_date) = '06'";
$result = mysqli_query($link_id,$sql);
if(!$result) die(sql_error());
$db1= Array();
$InList = '';
while( $row = mysqli_fetch_array($result,MYSQL_ASSOC) ) {
$InList .= sprintf("'%s',", $row['domain_name']);
$db1[$row['domain_name']] = $row['renewal_date'];
}
$InList = rtrim($InList, ',');
$sql = "select d_due_date, d_name
from domains
where d_domain IN ($InList)";
$result = mysqli_query($link_id1,$sql);
if(!$result) die(sql_error());
echo '<table>';
while( $row = mysqli_fetch_array($result,MYSQL_ASSOC ){
echo '<tr>';
echo '<td>' . $row['d_name'] . '</td>';
// find the db1.renewal_date matching d_name from db1 array
echo '<td>' . $db1[$row['d_name']] . "</td>";
echo '<td>' . $row['d_due_date'] . '</td>';
echo "</tr>";
}
echo '</table><br />';
RE: Your comment
So now I have saved the data from db1 into an array you can use the get the db1.renewal_date from in the output phase. Also I added the db1.d_name to the second query so you have the key to the array containing the db1.renewal_date
RE: Using more fields from table1:
Sure, thats not a problem. This will mean that you have to store an array i.e. the $row as the data so you have the complete set of columns saved in the $db1 array.
$sql = "select domain_name, renewal_date, f3, f4
from table1
where MONTH(renewal_date) = '06'";
$result = mysqli_query($link_id,$sql);
if(!$result) die(sql_error());
$db1= Array();
$InList = '';
while( $row = mysqli_fetch_array($result,MYSQL_ASSOC) ) {
$InList .= sprintf("'%s',", $row['domain_name']);
$db1[$row['domain_name']] = $row;
}
$InList = rtrim($InList, ',');
The $db1 array will now look like this:
Array
(
[abc.com] => Array
(
[domain_name] => abc.com
[renewal_date] => 2015-06-06
[f3] => aaa
[f4] => bbb
)
[xyz.com] => Array
(
[domain_name] => xyz.com
[renewal_date] => 2015-06-07
[f3] => ccc
[f4] => ddd
)
)
So the domain name is still the KEY to each occurance of the array, but you have another array associated with the key rather than just a single string.
So to access this array you do this to use a domains specific columns.
echo '<td>' . $db1[ $row['d_name'] ] ['renewal_date'] . "</td>";
echo '<td>' . $db1[ $row['d_name'] ] ['f3'] . "</td>";
echo '<td>' . $db1[ $row['d_name'] ] ['f4'] . "</td>";
I hope that is explained well enough to help you.
First of all, you can do this in just one database with multiple tables which would be nicer and easier to use than you should be able to do something like:
SELECT domain_name,renewal_date,d_due_date
FROM table1 INNER JOIN table2
ON table2.d_name = table1.domain_name
WHERE MONTH(table1.renewal_date) = '06'";
Something like this(also see this as referance)
using where and inner join in mysql
I think that due to use of && operator in while loop. There may be one of the table's result is empty and that's why the result set may be empty.
I am trying to create reports based on data from a log in the database that looks like:
id | student | type | marks
1 23494 CAT1 50
2 23495 CAT1 20
3 23494 CAT2 35
4 23495 MIDTERM 40
My select statement so far looks like this:
$res = #mysqli_query ($dbc, "SELECT id, student, type, GROUP_CONCAT(marks) AS mark, GROUP_CONCAT(type) AS types FROM log WHERE class = '1' AND term = '2' GROUP BY student DESC");
// Fetch and print all the records....<br>
while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC)) {
echo '<tr>
<td align="left">'. $row['student'] .'</td>';
//$exams = split(",", $row['exams']); // 4,3,1,2
$marks = split(",", $row['mark']); // 10,20,40,50
foreach( $marks as $mark ) {
echo '
<td align="left">' . $mark . '</td>
';
}
echo '</tr>';
} //End LOOP
//Then i end table
So far the data displays like so:
STUDENT | CAT1 | CAT2 | MIDTERM
23494 50 35
23495 20 40
The problem is that the code is not arranging 'marks' according to 'type' (look at MIDTERM output for id 4 and corresponding display).
Question:
How do i display the results by student, followed by marks in the appropriate cell/group like so:?
STUDENT | CAT1 | CAT2 | MIDTERM
23494 50 35
23495 20 40
Thanks in Advance Guys.
First, try to keep logic away from layout. It's generally good practice to first gather the data you need, and then display it.
Using GROUP_CONCAT can make things more complicated, since you do not know how many results you will get for each student, nor will you be able to easily identify which marks are of what type.
With that in mind I've created a solution. You'll still need to extend the query of course.
$query = 'SELECT student, type, marks FROM log';
$res = mysqli_query($query);
$studentMarks = array();
while ($row = mysqli_fetch_array($res, MYSQLI_ASSOC))
{
$studentMarks[$row['student']][$row['type']] = $row['marks'];
}
// Now $studentMarks should look like:
// $studentMarks = array(
// 23494 => array('CAT1' => 50, 'CAT2' => 35)
// , 23495 => array('CAT1' => 20, 'MIDTERM' => 40)
// );
echo '<table><thead><tr>';
echo '<td>Student</td><td>CAT1</td><td>CAT2</td><td>MIDTERM</td>';
echo '</tr></thead><tbody>';
foreach($studentMarks as $studentId => $marks)
{
echo '<tr>';
echo '<td>', $studentId, '</td>';
echo '<td>', (isset($marks['CAT1']) ? $marks['CAT1'] : ' '), '</td>';
echo '<td>', (isset($marks['CAT2']) ? $marks['CAT2'] : ' '), '</td>';
echo '<td>', (isset($marks['MIDTERM']) ? $marks['MIDTERM'] : ' '), '</td>';
echo '</tr>';
}
echo '</tbody></table>';
in my query i want only from id 1-3 to appear in the result, not 4-6. is there any other way to do it?
beautician database table:
id_beautician name
1 a
2 b
3 c
4 d
5 e
6 f
i tried to put the code below in mysql query
for($i=4; $i<=6; $i++) :
$q.$i = $db->query("SELECT * FROM beautician WHERE id_beautician='$i'");
$r.$i = $q.$i->fetch_assoc();
//echo $i;
endfor;
but it gives me an error:
Object of class mysqli_result could
not be converted to string
Instead of doing n queries, modify SQL query to match only data you need - for example:
$query = $db->query("SELECT * FROM beautician WHERE id_beautician <= 3");
while ( $row = $query->fetch_assoc() ) {
echo $row['id'] . ' = ' . $row['name'] . '<br/>';
}
If ids are not in sequence, you can also use as below.
$query = $db->query("SELECT * FROM beautician WHERE id_beautician in (1,2,3)");
while ( $row = $query->fetch_assoc() )
{
echo $row['id'] . ' = ' . $row['name'] . '<br/>';
}
using IN in query sometimes slow down the execution, but can be used efficiently for small-size database.
I'm building a form with php/mysql. I've got a table with a list of locations and sublocations. Each sublocation has a parent location. A column "parentid" references another locationid in the same table. I now want to load these values into a dropdown in the following manner:
--Location 1
----Sublocation 1
----Sublocation 2
----Sublocation 3
--Location 2
----Sublocation 4
----Sublocation 5
etc. etc.
Did anyone get an elegant solution for doing this?
NOTE: This is only psuedo-code.. I didn't try running it, though you should be able to adjust the concepts to what you need.
$parentsql = "SELECT parentid, parentname FROM table";
$result = mysql_query($parentsql);
print "<select>";
while($row = mysql_fetch_assoc($result)){
$childsql = "SELECT childID, childName from table where parentid=".$row["parentID"];
$result2 = mysql_query($childsql);
print "<optgroup label=\".$row["parentname"]."\">";
while($row2 = mysql_fetch_assoc($result)){
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>";
}
print "</select>";
With BaileyP's valid criticism in mind, here's how to do it WITHOUT the overhead of calling multiple queries in every loop:
$sql = "SELECT childId, childName, parentId, parentName FROM child LEFT JOIN parent ON child.parentId = parent.parentId ORDER BY parentID, childName";
$result = mysql_query($sql);
$currentParent = "";
print "<select>";
while($row = mysql_fetch_assoc($result)){
if($currentParent != $row["parentID"]){
if($currentParent != ""){
print "</optgroup>";
}
print "<optgroup label=\".$row["parentName"]."\">";
$currentParent = $row["parentName"];
}
print "<option value=\"".$row["childID"]."\">".$row["childName"]."</option>\n";
}
print "</optgroup>"
print "</select>";
Are you looking for something like the OPTGROUP tag?
optgroup is definitely the way to go. It's actually what it's for,
For example usage, view source of http://www.grandhall.eu/tips/submit/ - the selector under "Grandhall Grill Used".
You can use and space/dash indentation in the actual HTML. You'll need a recusrive loop to build it though. Something like:
<?php
$data = array(
'Location 1' => array(
'Sublocation1',
'Sublocation2',
'Sublocation3' => array(
'SubSublocation1',
),
'Location2'
);
$output = '<select name="location">' . PHP_EOL;
function build_items($input, $output)
{
if(is_array($input))
{
$output .= '<optgroup>' . $key . '</optgroup>' . PHP_EOL;
foreach($input as $key => $value)
{
$output = build_items($value, $output);
}
}
else
{
$output .= '<option>' . $value . '</option>' . PHP_EOL;
}
return $output;
}
$output = build_items($data, $output);
$output .= '</select>' . PHP_EOL;
?>
Or something similar ;)
Ideally, you'd select all this data in the proper order right out of the database, then just loop over that for output. Here's my take on what you're asking for
<?php
/*
Assuming data that looks like this
locations
+----+-----------+-------+
| id | parent_id | descr |
+----+-----------+-------+
| 1 | null | Foo |
| 2 | null | Bar |
| 3 | 1 | Doe |
| 4 | 2 | Rae |
| 5 | 1 | Mi |
| 6 | 2 | Fa |
+----+-----------+-------+
*/
$result = mysql_query( "SELECT id, parent_id, descr FROM locations order by coalesce(id, parent_id), descr" );
echo "<select>";
while ( $row = mysql_fetch_object( $result ) )
{
$optionName = htmlspecialchars( ( is_null( $row->parent_id ) ) ? "--{$row->descr}" : "----{$row->desc}r", ENT_COMPAT, 'UTF-8' );
echo "<option value=\"{$row->id}\">$optionName</option>";
}
echo "</select>";
If you don't like the use of the coalesce() function, you can add a "display_order" column to this table that you can manually set, and then use for the ORDER BY.