MYSQL and PHP group results by field data - php

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>';

Related

PHP/SQL - How can I display distinct values and the number of occurrences?

So I am currently using PHP to pull the bodies from emails, parse the data, and insert the data into a user-created DB. I want to display an overview of the data (that is inside the DB) using PHP. Here is an example of what I want to achieve:
This is my table:
Table Name: bldgSensors
sensor_code | temp_limit | current_temp
---------------------------------------
0102260100A | 55 | 45
0102260100B | 55 | 50
0102260100A | 55 | 48
Desired output using PHP:
Sensors Count
0102260100A 2
0102260100B 1
So far, I can find distinct values but cannot output the total count:
$result1 = mysqli_query($DBconn,"SELECT DISTINCT sensor_code FROM bldgSensors");
echo "<table border='1'>
<tr>
<th>Distinct sensor codes</th>
<th>Count</th>
</tr>";
while($row1 = mysqli_fetch_array($result1))
{
echo "<tr>";
echo "<td>" . $row1['sensor_code'] ."</td>";
}
echo "</table>";
mysqli_close($DBconn);
Thanks so much in advance! This will help tremendously!
You can do that by modifying your query. Use the COUNT and GROUP BY sql functions:
Try this:
$query = "SELECT
sensor_code,
COUNT(sensor_code) AS sensorCount
FROM bldgSensors
GROUP BY sensor_code
ORDER BY sensorCount DESC";
$result1 = mysqli_query($DBconn, $query);
echo
'<table border="1">
<tr>
<th>Distinct sensor codes</th>
<th>Count</th>
</tr>';
while($row1 = mysqli_fetch_array($result1)){
echo
'<tr>' .
'<td>' . $row1['sensor_code'] . '</td>' .
'<td>' . $row1['sensorCount'] . '</td>' .
'</tr>';
}
echo
'</table>';
mysqli_close($DBconn);

PHP MySQL split output into sections

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

SELECT SUM data rank and Resource id #9 error PHP

I have a website in which logged in members are stored under a table called ‘users’
‘users’ table
users_sales_guild_id | users_first_name | users_surname
555 | Jane | Smith
333 | John | Smith
111 | Mike | Myers
The users have sales data in a 'sales_points' field which is in a separate table called ‘sales_list’.
‘sales_list’ table
sales_id | users_sales_guild_id | sales_points | sales_entry_date
1 | 555 | 50 | 2013-02-31 00:00:00
2 | 333 | 30 | 2013-02-31 00:00:00
3 | 111 | 10 | 2013-02-31 00:00:00
4 | 555 | 50 | 2013-03-31 00:00:00
5 | 333 | 30 | 2013-03-31 00:00:00
6 | 111 | 10 | 2013-03-31 00:00:00
Essentially what I am trying to do is a query which:
A. Calculates the total amount of 'sales_points' for each user from 'sales_list'
B. Lists 100 users with the user having the most points at the top, then ranking the next highest below and so on...
C. Im not after a ranking number, just the order itself.
With the code below I am getting 100 users printing ok, however I am getting a ‘Resource id #9’ message in the ’Total Points’ column when it prints. Can anyone help?
What I am trying to print
Jane Smith | 100
John Smith | 60
Mike Myers | 20
Code:
<?php
require_once ('config.inc.php');
$page_title = '';
include ('header.html');
if (!isset($_SESSION['users_id'])) {
$url = 'http://' . $_SERVER['HTTP_HOST']
. dirname($_SERVER['PHP_SELF']);
// Check for a trailing slash.
if ((substr($url, -1) == '/') OR (substr($url, -1) == '\\') ) {
$url = substr ($url, 0, -1); // Chop off the slash.
}
// Add the page.
$url .= 'login.php';
ob_end_clean(); // Delete the buffer.
header("Location: $url");
exit(); // Quit the script.
}?>
<h1>Rankings</h1>
<?php require_once ('database.php'); // Connect to the database.
$total = mysql_query("SELECT SUM(sales_points) FROM sales_list,users WHERE sales_list.users_sales_guild_id = users.users_sales_guild_id
AND sales_entry_date
BETWEEN '2013-10-01 00:00:00' AND '2013-11-30 23:59:59'
" );
$query = "SELECT us.users_id, us.dealership_id, us.users_sales_guild_id, us.users_first_name, us.users_surname, us.users_type,
de.dealership_id, de.users_dealer_name, de.class , de.region, de.state, de.users_dealer_code_id, de.users_dealer_code_new_id, de.users_model, de.pma
FROM users AS us, dealerships AS de
WHERE us.dealership_id = de.dealership_id
ORDER BY ’$total’ DESC
LIMIT 100";
$result = #mysql_query ($query);
// Table header.
echo '<table width="680"cellpadding="5" cellspacing="1" style="font-size:12px;">
<tr class="orangehead">
<td align="center"><b>Member</b></td>
<td align="center"><b>Title</b></td>
<td align="center"><b>Dealer</b></td>
<td align="center"><b>Category</a></b></td>
<td align="center"><b>Dealer Code</a></b></td>
<td align="center"><b>Total Points</a></b></td>
</tr>';
// Fetch and print all the records. echo '<td align="left"><strong>' . $row['sp_invoice_no'] . '</strong></td> ';
$bg = '#ffffff'; // Set the background color.
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$bg = ($bg=='#eaeced' ? '#ffffff' : '#eaeced'); // Switch the background color. New: ' . $row['users_sales_guild_new_id'] . '
// $entries = floor($row['sp_entry_amount']/200);
echo '<tr bgcolor="' . $bg . '">';
echo '<td align="left"><strong>' . $row['users_first_name'] . ' ' . $row['users_surname'] . '</strong></td> ';
echo '<td align="center">' . $row['users_type'] . ' </td>';
echo '<td align="center"> ' . $row['users_dealer_name'] . ' </td>';
echo '<td align="center"> ' . $row['class'] . ' </td>';
echo '<td align="center"> ' . $row['users_sales_guild_id'] . ' </td>';
echo '<td align="center"> ' . $total . '</td>';
echo '</tr>
';
}
echo '</table>';
mysql_free_result ($result); // Free up the resources.
mysql_close(); // Close the database connection.
include ('footer.html'); // Include the HTML footer.
?>
You don't fetch you first result. Fetch it as an array (mysql_fetch_array()) for example.
// Execute query
$total_query = mysql_query("SELECT SUM(sales_points)
FROM sales_list, users
WHERE sales_list.users_sales_guild_id = users.users_sales_guild_id
AND sales_entry_date
BETWEEN '2013-10-01 00:00:00' AND '2013-11-30 23:59:59'");
// Fetch result
$total = mysql_fetch_array($total_query);
You echo this:
$total = mysql_query("SELECT SUM(sales_points) FROM sales_list,users WHERE sales_list.users_sales_guild_id = users.users_sales_guild_id
AND sales_entry_date
BETWEEN '2013-10-01 00:00:00' AND '2013-11-30 23:59:59'
" );
The variable $total contains the result of the query, which is a Resource. You should use mysql_fetch_assoc or a similar function to extract the result itself. It's best to give the SUM(sales_points) an alias, i.e. AS total_sales_points so you can fetch is easily.
By the way, the mysql_*-extension is soon-to-be deprecated. Good alternatives include MySQLi and PDO.
$query = mysql_query("SELECT SUM(sales_points) as points FROM sales_list,users WHERE sales_list.users_sales_guild_id = users.users_sales_guild_id
AND sales_entry_date
BETWEEN '2013-10-01 00:00:00' AND '2013-11-30 23:59:59'
" );
$row = mysql_fetch_object($query);
$total = $row->points;
You are echoing the mysql resource, you first need to fetch the results, then you can echo them.

How to display multiple records with same id in html table in single row(in <td>)?

I have sql data result set having records as follows
id | name | hobbies
------------------------------------
1 | RAVI | PLAYING CRICKET
------------------------------------
1 | RAVI | LISTENING MUSIC
------------------------------------
2 | REENA | BADMINTON
------------------------------------
I am displaying this data in view by using html table.
Whereas my requirement is, I want to display as follows
id | name | hobbies
------------------------------------
1 | RAVI | PLAYING CRICKET
| | LISTENING MUSIC
------------------------------------
2 | REENA | BADMINTON
------------------------------------
meaning I want to display records with id 1 into one <td>
I am using php foreach loop to display result.
How can I achieve this?
My current code is as follows and is results into same as my first table whereas I want my view as in the second table.
<table class="table table-striped">
<tr >
<th>ID</th>
<th>Name</th>
<th>Hobbies</th>
</tr>
foreach($result as $row)
{
echo "<tr>
<td>".$row->id."</td>
<td>". $row->name."</td>
<td>". $row->hobbies."</td>
</tr>";
}
</table>
A quick way to approach this would be to modify your MySQL query to use GROUP_CONCAT(hobbies) to group all of a user's hobbies together. The query would look something like:
SELECT
id, name, GROUP_CONCAT(hobbies) AS hobbies
FROM
your_table
GROUP BY
id
This will group all of a user's hobbies in a comma-delimited list. To display it, you can use PHP's explode() and iterate over that:
foreach ($results as $row) {
echo '<tr>';
echo '<td>' . $row->id . '</td>';
echo '<td>' . $row->name . '</td>';
echo '<td>';
$hobbies = explode(',', $row->hobbies);
foreach ($hobbies as $hobby) {
// output each hobby and decorate/separate them however you'd like
echo $hobby . '<br />';
}
echo '</td>';
echo '</tr>';
}
If you don't want the inner loop (or the ending <br /> that will pad the hobbies), you can use str_replace() instead:
echo str_replace(',', '<br />', $result['hobbies']);
This post may help you: Concatenate many rows into a single text string?
Just replace the , with </br>.
in each iteration, you must save the last ID, in the next iteration you must check it whether its value has been changed or not. Something like this:
$res = $this->db->query('.....');
$last_ID = '';
foreach ($res->result() as $row) {
if ($row->id != $last_ID) {
if (strlen($last_ID)>0) echo '</td></tr>';
echo '<tr>';
echo '<td>$row->id</td>';
echo '<td>$row->name</td>';
echo '<td>$row->hobbies';
} else {
echo '<br />'.$row->hobbies;
}
$last_ID = $row->id;
}
if ($res->num_rows() > 0) echo '</td></tr>';
Supposing you have your row in $row var and the ID is $row["ID"]
?>
<td id="<php echo $row["id"]; ?>">
<?php echo $row["id"]; ?>
</td>
<?php

Nested dropdown

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.

Categories