I have two tables, result and gp.
In the result table I have something like this:
|id||student_id ||course_code||grade||session ||level||semester|
|1 ||TR/2213234561||MAT111 ||A ||2009/2010||100 ||first |
|2 ||TR/2213234561||MAT112 ||B ||2009/2010||100 ||first |
|3 ||TR/2213234561||MAT113 ||C ||2009/2010||100 ||first |
|4 ||TR/2213234567||MAT111 ||D ||2009/2010||200 ||first |
|5 ||TR/2213234567||MAT112 ||C ||2009/2010||200 ||first |
|6 ||TR/2213234567||MAT113 ||C ||2009/2010||200 ||first |
Then gp table
|id||student_id ||session ||level||semester||gp |
|1 ||TR/2213234561||2009/2010||100 ||first ||4.2|
|2 ||TR/2213234567||2009/2010||100 ||first ||3.5|
|3 ||TR/2213234561||2010/2011||200 ||first ||4.2|
|4 ||TR/2213234567||2010/2011||200 ||first ||3.5|
What I want is like this:
|Matriculation||MAT111||MAT112||MAT113||MAT114||GP |
|TR/2213234561||A ||B ||D ||C ||4.2|
|TR/2213234567||C ||D ||E ||F ||3.5|
The course code are not constant - it depends on the course registered by the students
I have done this:
<?php
$rst1 = mysql_query("select distinct course_code from result ", $conn);
echo "<table callspacing='4'>";
echo "<tr>";
echo "<td> Matriculation Number </td>";
$c_code = array();
while ($row = mysql_fetch_array($rst1))
{
$c_code[] = $row['course_code'];
}
foreach($c_code as $c_code)
{
echo "<td>" .$c_code. "</td>";
}
$sql ="SELECT result.student_id,
MAX(CASE WHEN course_code = ' $c_code' THEN grade END) $c_code,
gp.CTC
FROM result
JOIN gp
ON gp.student_id = result.student_id
GROUP
BY student_id";
echo "<td> GP</td>";
$rst = mysql_query("$sql",$conn) or die(mysql_error());
while ($row = mysql_fetch_array($rst))
{
echo "</tr>";
echo "<tr>";
echo "<td>" .$row['student_id']. "</td>";
echo "<td>" .$row[$c_code]. "</td>";
}
echo "<td>" .$row[$c_code]. "</td>";
echo "<td>" .$row['CTC']. "</td>";
echo"</tr>";
echo "</table>";
?>
The first query was to get the course code, since the courses are not constants.
with that code, I got something like this:
|Matriculation||MAT111||MAT112||MAT113||MAT114||GP|
|TR/2213234561|
|TR/2213234567|
But I wanted
|Matriculation||MAT111||MAT112||MAT113||MAT114||GP |
|TR/2213234561||A ||B ||D ||C ||4.2|
|TR/2213234567||C ||D ||E ||F ||3.5|
Any suggestion or direction will be highly appreciated.
What you wish to do is known as "pivoting" your data and is something for which some other RDBMS have native support, but MySQL does not (by design, as the developers feel that such manipulations belong in the presentation layer).
However, you have a few options:
Construct a rather horrible MySQL query to perform the pivoting operation manually:
SELECT student_id AS Matriculation, MAT111, MAT112, gp AS GP
FROM gp
NATURAL JOIN (
SELECT student_id, grade AS MAT111
FROM result
WHERE course_code = 'MAT111'
) AS tMAT111
NATURAL JOIN (
SELECT student_id, grade AS MAT112
FROM result
WHERE course_code = 'MAT112'
) AS tMAT112
-- etc.
WHERE level = #level AND semester = #semester
If you choose to go down this path, you can make your life slightly easier by generating this query automatically, using either a looping construct in PHP or a prepared statement in MySQL.
Here is one way that you could do that in PHP:
Obtain a list of courses:
$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', $user, $password);
$qry = $dbh->query("SELECT DISTINCT course_code FROM result [WHERE ...]");
$courses = $qry->fetchAll(PDO::FETCH_COLUMN, 0);
Loop over the results, constructing the above SQL:
mb_regex_encoding($charset);
$columns = mb_ereg_replace('`', '``', $courses);
$sql = "
SELECT student_id AS Matriculation, `".implode("`,`", $columns)."`, gp AS GP
FROM gp";
foreach ($columns as $column) $sql .= "
NATURAL JOIN (
SELECT student_id, grade AS `$column`
FROM result
WHERE course_code = ?
) AS `t$column`";
$sql .= "
WHERE level = ? AND semester = ?";
Execute the SQL, passing in the array of courses as parameters:
$qry = $dbh->prepare($sql);
$params = $courses;
array_push($params, $level, $semester);
$qry->execute($params);
Output the results:
echo "<table>";
echo "<tr>";
for ($i = 0; $i < $qry->columnCount(); $i++) {
$meta = $qry->getcolumnMeta($i);
echo "<th scope='col'>" . htmlentities($meta['name']) . "</th>";
}
echo "</tr>";
while ($row = $qry->fetch(PDO::FETCH_NUM)) {
echo "<tr>";
foreach ($row as $field) echo "<td>" . htmlentities($field) . "</td>"
echo "</tr>";
}
echo "</table>";
Do the above as a one-off operation so that the structure of your MySQL database is changed to more closely reflect this desired layout (easy once table is converted, but may impact other uses of the database):
CREATE TABLE StudentGrades (PRIMARY KEY('Matriculation'))
SELECT student_id AS Matriculation, MAT111, MAT112, gp AS GP
-- etc. as above
Alternatively, you can create a VIEW which is a sort of "virtual table" structured in this way based on the underlying table.
Pivot the data manually in PHP (relatively tedious).
Related
I have 2 tables
1)students
students table looks like
stu_slno stu_gr stu_name
1 1 ABCDESDFDGFJ
2 3 KJJJHJILKJBJB
3 5 HAHAHAHAHKJHKJH
4 1 BBJHBAHJBHJBAJHK
2)groups
groups table looks like
sl_no pg_groups
1 01-M.A HISTORY
3 03-M.A SOCIOLOGY
5 04-M.A ECONOMICS
i have inserted data into students with groups serial numbers
when i am retrieving data from students i will get the groups serial number but what i want is to group names corresponding to the serial number
my code is of retrieving
<?PHP
$sql="SELECT * FROM students";
if ($us=$conn->query($sql)){;
if ($us->num_rows > 0) {
echo '<table border="2">';
echo "<tr>";
echo "<th>Slno</th>";
echo "<th>Name</th>";
echo "<th>Group</th>";
echo "</tr>";
while($row = $us->fetch_assoc()) {
echo "<tr>";
echo "<td>" .$i++. "</td>";
echo "<td>" .$row['stu_name']. "</td>";
echo "<td>" .$row['stu_gr']. "</td>";
echo "</table>";
}
}
}
?>
use join in query like this:
$sql="SELECT stu_slno, pg_groups, stu_name
FROM students s
INNER JOIN groups g ON g.pg_groups = s.stu_gr";
$sql = "SELECT s.*, g.pg_groups from students AS s LEFT JOIN groups as g ON g.sl_no = s.stu_gr";
TO display in the HTML table, use the below code
echo "<td>" .$row['pg_groups']. "</td>";
How to create a table with data retrieved from MySQL with PHP
-------------------------
| albumID | trackID |
-------------------------
| | 1990 |
- 1 -------------
| | 1991 |
-------------------------
| | 1992 |
- -------------
| 2 | 1993 |
- -------------
| | 1994 |
-------------------------
I can generate a table from the database, but the result will be only like each result in one row
$query = "SELECT albumID, trackID
FROM songs";
$result = mysqli_query($db, $query);
echo "<table>";
echo "<tr>\n";
echo "<th>albumID</th>\n";
echo "<th>trackID</th>\n";
echo "</tr>\n";
while ($data = mysqli_fetch_array($result)) {
echo "<tr>\n";
echo "<td>$data[0]</td>\n";
echo "<td>$data[1]</td>\n";
echo "</tr>\n";
}
echo "</table>\n";
Any help given is really appreciated!
You can do this by using a variable to keep track of the current album and only output the album once as shown below.
$current_album = ''; # initialize tracking var
while ($data = mysqli_fetch_array($result)) {
echo "<tr>\n";
if ($current_album != $data[0]) {
echo "<td>$data[0]</td>\n";
$current_album = $data[0];
} else {
echo "<td> </td>\n"; # insert empty cell
}
echo "<td>$data[1]</td>\n";
echo "</tr>\n";
}
This will have the album ID appearing in the first row for the album. If you want it to be vertically centered you can use rowspan on the td element, but in order to know how many rows each album has you will either need to update your sql query to return that or you can process the results into a multidimensional array and then loop through that to generate the output.
Maybe not the most elegant solution, but should do the trick.
$query = "select albumID as album, group_concat(trackID) as tracks from songs group by albumID";
$result = mysqli_query($db, $query);
echo "<table>";
echo "<tr>\n";
echo "<th>albumID</th>\n";
echo "<th>trackID</th>\n";
echo "</tr>\n";
while ($data = mysqli_fetch_array($result)) {
$tracks = explode(",", $data[1]);
echo "<tr>\n";
echo "<td rowspan=\"".count($tracks)."\">$data[0]</td>\n";
foreach ($tracks as $key => $value) {
echo "<td>$value</td>\n"
}
echo "</tr>\n";
}
echo "</table>\n";
Edit your query to return the numbers of tracks of the album and use that number to create a rowspan only on the first track row. I wrote a little example but I havn't tried if it works.
$query = "SELECT s.albumID, s.trackID,
( SELECT COUNT(*)
FROM songs s2
WHERE s2.albumID = s.albumID )
FROM songs s";
$result = mysqli_query($db, $query);
echo "<table>";
echo "<tr>\n";
echo "<th>albumID</th>\n";
echo "<th>trackID</th>\n";
echo "</tr>\n";
$tmpAlbum = '';
while ($data = mysqli_fetch_array($result)) {
echo "<tr>\n";
echo "<td";
if($data[2] == 1){
echo "<td>$data[0]</td>\n";
}else{
if($data[0] != $tmpAlbum){
echo "<td rowspan=\"".$data[2]."\">$data[0]</td>\n";
}
}
$tmpAlbum = $data[0];
echo "<td>$data[1]</td>\n";
echo "</tr>\n";
}
echo "</table>\n";
I am making a soccer site. I have the following table structure:
season1 (name of the table)
id | player1 | player2 | score
I want to put the scores into a html table. This table is only for player called nickname1 vs every other player. I have this:
$query = mysql_query("SELECT * FROM season1 WHERE player1='nickname1'") or die(mysql_error());
while($row = mysql_fetch_array( $query )) {
echo "<tr><td>";
echo "";
echo "</td><td>";
echo $row['score2'];
echo "</td><td>";
echo $row['score3'];
echo "</td><td>";
echo $row['score4'];
echo "</td><td>";
echo $row['score5'];
echo "</td></tr>";
}
echo "</table> <br>";
Instead of $row['score2'] I need the score between nickname1 vs
nickname2
Instead of $row['score3'] I need the score between nickname1 vs
nickname3
Instead of $row['score4'] I need the score between nickname1 vs
nickname4
Instead of $row['score5'] I need the score between nickname1 vs
nickname5
I tried SELECT * FROM season1 WHERE player1='nickname1' AND player2='nickname2' but then it will show only player1 vs player2 in the table. I want to show all 4 players vs player1 in the same table.
Assuming score1 it's player 1 score:
$query = mysql_query("SELECT * FROM season1 WHERE player1='nickname1'") or die(mysql_error());
while($row = mysql_fetch_array( $query )) {
echo "<tr><td>";
echo "";
echo "</td><td>";
echo $row['player1']." vs ".$row['player2'].", with a score of: ".$row['score'];
echo "</td></tr>";
}
echo "</table> <br>";
I hope it helps.
Saludos ;)
You need to focus your loop only on making one row:
echo "<table><tr>";
while($row = mysql_fetch_array( $query )) {
echo "<td>{$row['score']}</td>";
}
echo "</tr></table>";
This will ONLY output the scores of the players. You can modify it to have nickname headers and so forth.
Take note that the $row array resembles your table structure. $row['score'] will give you the scores of the players where as since score1 is not a column in the table, it does not exist in $row.
Possible design:
echo "<table><tr><th>Player 1</th><th>Player 2</th><th>Score</th></tr><tr>";
while($row = mysql_fetch_array( $query )) {
echo "<td>{$row['player1']}</td>";
echo "<td>{$row['player2']}</td>";
echo "<td>{$row['score']}</td>";
}
echo "</tr></table>";
will output (depending on ID's in database)
Player 1 | Player 2 | Score
p1 p2 0
p1 p3 0
NOTICE: MySQL_* has been deprecated in PHP 5.5. Use MySQLi or PDO instead
I need help with DISTINCT. I would like to display Distinct row but display also all rows
Example this table from database:
+----+-----+-----+
|col1|col2 |col3 |
+----+-----+-----+
|A |one |two |
|A |three|four |
|A |five |six |
|B |seven|eight|
|B |nine |ten |
+----+-----+-----+
I would like the display to look like this :
A
one |two
three|four
five |six
B
seven|eight
nine |ten
Can anyone help?
The easiest way would be to fetch all rows from the database, and then group them in PHP.
// Querying:
$query = mysql_query('select * from tbl');
$results = array(); // Store all results in an array, grouped by col1
while($row = mysql_fetch_assoc($query)) {
$col1 = $row['col1'];
// This is basically grouping your rows by col1
if(!isset($results[$col1]))
$results[$col1] = array();
$results[$col1][] = $row;
}
// Displaying:
foreach($results as $col1 => $rows) {
echo "<h1>" . $col1 . "</h1>";
foreach($rows as $row) {
echo $row['col2'] . "|" . $row['col3'] . "<br />";
}
}
Yields:
<h1>A</h1>
one |two
three|four
five |six
<h1>B</h1>
seven|eight
nine |ten
Note that I use the deprecated mysql_functions just for simplicity, do not use them in production.
Here is how you can do it
$query="select
distinct (col1) as col1,
GROUP_CONCAT(col2) as col2,
GROUP_CONCAT(col3) as col3
FROM test
group by col1";
$query = mysql_query($query);
This will fetch this output
col1 col2 col3
A one,three,five two,four,six
B seven,nine eight,ten
while($row = mysql_fetch_assoc($query))
{
$col1 = $row['col1'];
$col2 = explode(',',$row['col2']);
$col3 = explode(',',$row['col3']);
for($i=0;$i<=count($col2);$i++)
{
$value = '';
if(isset($col2[$i])){
$value = $col2[$i];
$value .= ' | ';
}
if(isset($col3[$i])){
$value .= $col3[$i];
}
echo $value;
}
}
I have a small problem with MySQL tables pushed into a HTML table.
Here is my SELECT on the database:
$result = mysql_query("
SELECT dat_eb_registrants.id, dat_eb_registrants.first_name, dat_eb_registrants.last_name, dat_eb_registrants.email, dat_eb_registrants.comment, dat_eb_registrants.amount, dat_eb_registrants.published, dat_eb_registrants.transaction_id, dat_eb_registrants.register_date, GROUP_CONCAT(dat_eb_field_values.field_value SEPARATOR '</td><td>')
FROM dat_eb_registrants LEFT JOIN dat_eb_field_values ON dat_eb_registrants.id=dat_eb_field_values.registrant_id
WHERE `event_id` >= 20 AND `event_id` <= 25
GROUP BY dat_eb_registrants.id
ORDER BY $sort $ascdsc
");
Which is pushed into my HTML table using this:
while ($row = mysql_fetch_row($result)) {
echo "<tr>";
echo "<td>" . $row[9] . "</td>";
echo "<td>";
Now, my problem is the fact that this fills my table with a few rows from dat_eb_field_values.field_value, and I can't get other rows ($row[0] to $row[8]) in-between these results.
For example if my $values come from dat_eb_field_values.field_value and my $data comes from dat_eb_registants. This would be my table:
| header 1 | header 2 | header 3 | header 4 | header 5 | header 6 |
-------------------------------------------------------------------
| $value1 | $value2 | $data3 | $value4 | $data1 | $data2 |
| $value1 | $value2 | $data3 | $value4 | $data1 | $data2 |
| $value1 | $value2 | $data3 | $value4 | $data1 | $data2 |
Thanks in advance! Laurent
while ($row = mysql_fetch_row($result)) {
echo "<tr>";
foreach($row AS $val)
echo "<td>" . $val . "</td>";
echo "<td>";
}
that should do
Instead of echoing out the data of $row[9] place it in a array, then spit it out when you feel it's necessary (and after you've checked for the other elements)
For example change this:
while ($row = mysql_fetch_row($result)) {
echo "<tr>";
echo "<td>" . $row[9] . "</td>";
echo "<td>";
To this:
while ($row = mysql_fetch_row($result)) {
$myArray[] ="<tr><td>" . $row[9] . "</td>""<td>";
instead of mysql_fetch_row use mysql_fetch_array
and
ORDER BY $sort $ascdsc change it to
ORDER BY '".$sort."', '".$ascdsc."'
exemple :
by using mysql_fetch_array try echo this
echo $row['dat_eb_registrants.id'] ;
your sql is hard to read
use this
SELECT dr.id, dr.first_name, dr.last_name, dr.email, dr.comment, dr.amount, dr.published, dr.transaction_id, dr.register_date, GROUP_CONCAT(df.field_value SEPARATOR '</td><td>')
FROM dat_eb_registrants dr
LEFT JOIN dat_eb_field_values df
ON dr.id=df.registrant_id
WHERE `event_id` >= 20 AND `event_id` <= 25
GROUP BY dr.id
ORDER BY '".$sort."', '".$ascdsc."'
but you have accepted the answer here !!