Organizational Research By

Surprising Reserch Topic

displaying a table in php with repeated columns using -'c#,php,html,sql'


displaying a table in php with repeated columns  using -'c#,php,html,sql'

I have the following data in a MySQL database:

Autonum  ID  Name  MetaValue
1         1  Rose  Drinker
2         1  Rose  Nice Person
3         1  Rose  Runner
4         2  Gary  Player
5         2  Gary  Funny


I am working in PHP now but I have encountered this problem several times using C#, Java and other languages.

Now my goal in the past and present has been to display the data in the following format:

<table>
    <thead>
    <th>Name</th>
    <th>MetaValue1</th>
    </thead>
    <tbody>
           <tr>      
               <td>Rose</td>
                <td>
                    <ul>
                        <li>Drinker</li>
                        <li>Nice Person</li>
                        <li>Runner</li>
                     </ul>
                </td>
            </tr>
            <tr>
                <td>Gary</td>
                <td>
                    <ul>
                         <li>Player</li>
                         <li>Funny</li>
                 </td>
                </tr>
        </tbody>

</table>


I have tackled this problem before by creating a class that represents my SQL table.
Then I created a Dictionary to hold EmployeeId and the class.

Dictionary<string,MyTable> MyData = new <string,MyTable>();
Table MyMetaData = new Table();
MyMetaData SomeMetaData=getMetaValueList();//imagine a web service that does that
MyData.add(EmployeeId,SomeMetaData);


I am skipping steps but I hope you get my point. I probably just need keywords of what to call this type of problem. What is the preferred way to accomplish this?
    

asked Sep 8, 2015 by rajesh
0 votes
2 views



Related Hot Questions

14 Answers

0 votes
I do not like SQL solution for one reason. You ask database engine to join string and then you use PHP to split it. It is like repeated work. Another down side is that what if metavalue contains seperator character. My code just demonstrates how you can easily group data with 2 dimensional array in PHP and it is up to coder to decide which method to retrieve data from database either legacy mysql_* or PDO. // get result $result = mysql_query("SELECT autonum,id,name,metavalue FROM table"); // loop through each row while ($row = mysql_fetch_assoc($result)) { $table[$row['name']][] = $row['metavalue']; } // print it out print_r($table); There is no need to temporarily store the whole resultset into an array. You can iterate straight ahead by first sort data by what field you want to group your data and keep track of state. However, there are two reasons why I prefer this style and it is personal preference (it is not the must-must do solution): Usually, everyone want to separate logic and presentation apart. Storing data in array can be easily passed to your template engine. I prefer using PHP template engine for it is easy to implement and it runs at light speed. I would rather trade slight performance speed and memory usage for readability and maintainability. The algorithm is short and simple to understand. If performance is your top priority, you can always use cache such as storing in file, storing in memcached, or storing calculated result in database. True, we are grouping data from different side, but you assume that the metavalue does not contain separator (which in your code is |). It can be easily fixed by choosing separator that almost impossible to be used by metavalue. Anyway, your solution will works perfectly fine in almost every case because metavalue that @jvelez has shown will never contain character |.
answered Sep 8, 2015 by rajesh
0 votes
Please see your data, it is sorted and ordered: Autonum ID Name MetaValue 1 1 Rose Drinker 2 1 Rose Nice Person 3 1 Rose Runner 4 2 Gary Player 5 2 Gary Funny So what you can do is to solve that by the output: Each time the ID/Name changes, you have a new table row. Each time the MetaValue changes you have a new list entry. All you need to do is to do a look-ahead onto the next element to see the change. That means you iterate in advance (pre-calculated iteration) or you do a cached iteration (e.g. with CachingIterator in PHP). If you then keep track of the state as well, you can say per each entry whether: A table row needs to be opened before it. A table row needs to be closed after it. Actually it's even much more simple, here an array based rows iteration example (Demo): $rows = array( array(1, 1, 'Rose', 'Drinker'), array(2, 1, 'Rose', 'Nice Person'), array(3, 1, 'Rose', 'Runner'), array(4, 2, 'Gary', 'Player'), array(5, 2, 'Gary', 'Funny'), ); echo "<table>\n <thead>\n <th>Name</th>\n <th>MetaValue1</th>\n </thead>\n <tbody>\n"; $events = new Events(); $last = array(2 => null); foreach($rows as $row) { if ($last[2] !== $row[2]) { $events->newRow($row[2]); } $events->newItem($row[3]); $last = $row; } $events->closeRow(); echo " </tbody>\n</table>"; Not much code to solve your problem because the problem itself is just a little bit of state inside the data. What has been described as events here can be inverted by creating your own iterator which can be passed to a template system that supports iterators, e.g. twig or mustache. A full blown example of that is shown in previous answers of mine and inside a blog post: Getting nested set model into a but hiding √Ę
answered Sep 8, 2015 by rajesh
0 votes
The problem is not in the php/java/c# code, but in the SQL end of things. SELECT ID AS id, Autonum AS num, Name AS name, GROUP_CONCAT ( ORDER BY MetaValue DESC SEPARATOR '|' ) AS list FROM Things GROUP BY Things.ID This way you get a list of name values, and you all the associated MetaValues for that item, you just split the list on '|'. In PHP you do it with explode(), in C# with String.Split() and, I assume, that you will be able to find something similar for any language. Generation of HTML becomes quite trivial. Here is a PHP example ( with PDO connection API used ): $statement = $pdo->query( $sql ); if ( $statement->execute() ) { $data = $statement->fetchAll(PDO::FETCH_ASSOC); foeach ( $data as $row ) { echo '<tr><td>' , $row['name'] , '</td>'; echo '<td><ul><li>' , str_replace( '|', '</li><li>' , $row['list']) ; echo '</li></ul></td></tr>'; } } This would generate the <tbody> content from your example.
answered Sep 8, 2015 by rajesh
0 votes
Here is a solution, it is similar to @invisal's in the way we create an array based on a property of the table to group the results together. <?php $mysqli = new mysqli("localhost", "uname", "pword", "wordpress"); if ($mysqli->connect_errno) { die("Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error); } $res = $mysqli->query("SELECT * FROM wp_postmeta"); // array that will hold the final results $results = array(); // while we have more rows while ($row = $res->fetch_assoc()) { // check to see if we already have this ID if (!array_key_exists($row['ID'], $results)) { // if not create a new index for it in $results, which holds an array $results[$row['ID']] = array(); } // create new stdClass object that holds the row data $obj = new stdClass; $obj->Name = $row['Name']; $obj->MetaValue = $row['MetaValue']; // append this data to our results array based on the ID $results[$row['ID']][] = $obj; } ?> <table> <thead> <th>Name</th> <th>MetaValue</th> </thead> <tbody> <?php foreach($results as $id => $values): ?> <tr> <td style="vertical-align: top"><?php echo $values[0]->Name ?></td> <td> <ul> <?php foreach($values as $value): ?> <li><?php echo $value->MetaValue ?></li> <?php endforeach; ?> </ul> </td> </tr> <?php endforeach; ?> </tbody> </table> This seems to produce your desired results. Hope that helps.
answered Sep 8, 2015 by rajesh
0 votes
I would solve this in a different way. Right now, you're having issues because you're database schema is not normalized. Instead, I would start off by altering the schema. Right now, you have this: CREATE TABLE foo { `autonum` INT(12) NOT NULL AUTO_INCREMENT, `id` INT(12) NOT NULL, `name` VARCHAR(255) NOT NULL, `metaValue` VARCHAR(255) NOT NULL, PRIMARY KEY(autonum) ) Instead, I would split it out into two tables: CREATE TABLE user { `id` INT(12) NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NOT NULL, PRIMARY KEY(id) ) CREATE TABLE user_meta { `user_id` INT(12) NOT NULL, `value` VARCHAR(255) NOT NULL ) Ignoring the fact that this looks like an EAV table (which it isn't, meta is just mis-named due to the OP's naming), it should be clear how this is easier. So let's look at your record, and build up the table: #User id | name 1 | Rose 2 | Gary #User Meta user_id | value 1 | drinker 1 | Nice Person 1 | Runner 2 | Player 2 | Funny Now that we have the data, let's look at how we'd extract it. Let's assume that we always want to print out all users (limiting it would be simple, but for clarity, we can just do all for now). So, I would setup a simple class around each table here, caching the data into a single query. class User implements IteratorAggregate { protected $data = array(); public function __construct() { $query = mysql_query("SELECT id, name FROM user"); while ($row = mysql_fetch_assoc($query)) { $this->data[$row['id']] => $row['name']; } } public function getIterator() { return new ArrayObject($this->data); } } class User_Meta { protected $data = array(); public function __construct() { $query = mysql_query("SELECT user_id, value FROM user_meta"); while ($row = mysql_fetch_assoc($query)) { if (empty($this->data[$row['user_id']])) { $this->data[$row['user_id']] = array(); } $this->data[$row['user_id']][] = $row['value']; } } public function getDataForUserId($id) { return empty($this->data[$id]) ? array() : $this->data[$id]; } } Now, constructing the output becomes trivial: $users = new User; $meta = new User_Meta; echo "<table> <thead> <th>Name</th> <th>MetaValue1</th> </thead> <tbody>"; foreach ($users as $id => $name) { echo "<tr> <td>".htmlspecialchars($name)."</td> <td> <ul>"; foreach ($meta->getDataForUserId($id) as $metaValue) { echo "<li>" . htmlspecialchars($metaValue) . "</li>"; } echo " </ul> </td> </tr>"; } echo "</tbody></table>"; Now, with all of that said, I would personally implement it a bit different, using first-class business objects and data mappers for everything. And I did commit a few felonies here, but I did it for simplicity. Here's what I would have done differently: Not do logic in the constructor of an object. Instead, I would have injected it or used a factory to pre-populate the data. Abstract out the concept of the relationships into separate business objects. Separate out the pull logic from the display logic. Name things better (metavalue is not a good name for a field). But it really depends on the exact requirements of the application. There is no one (or two) right ways to do this. Each of the possible ways has pros and cons. Learn to weigh the tradeoffs so that you can pick the right one for your requirements...
answered Sep 8, 2015 by rajesh
0 votes
I had a similar table once and I ended up using some SQL to return the data as individual rows. I have modified my objects to use your sql and written a simple function that will output your data in the table following the format that you used in your question. The main query aggregate function that I used is the MySQL GROUP_CONCAT. This is similar to an implode() function. The default separator is a comma, so if you have commas in your metadata you can change it to a different marker by adding SEPARATOR 'yourSeparator' inside the brackets after the column name. You can also use a distinct infront of the column name to only select distinct rows in the group_concat. I have put the table header section inside the try statement, so that if you don't have any results, you won't be displaying a half-generated table. <?php class myUser { public $ID; public $name; public $metas; } class myTables { public $SQL=" select ID, name, GROUP_CONCAT(metavalue) as metas FROM table1 GROUP BY ID, name;"; public function outputTable() { $hostname="mysql:host=localhost;dbname=test"; $username="testdb"; $password="testdbpassword"; try{ echo " <table> <thead> <th>Name</th> <th>MetaValue</th> </thead> <tbody> "; $dbh = new PDO($hostname, $username, $password); $stmt = $dbh->query($this->SQL); $obj = $stmt->setFetchMode(PDO::FETCH_INTO, new myUser); foreach($stmt as $myUser) { echo " <tr><td>".$myUser->name."</td><td><ul>"; $metas=explode(",", $myUser->metas); for($i=0;$i<count($metas);$i++) { echo "<li>".$metas[$i]."</li>"; } echo "</ul></td></tr>"; } unset($obj); unset($stmt); unset($dbh); echo " </tbody> </table> "; } catch(PDOException $e){ echo 'Error : '.$e->getMessage(); exit(); } } } $myPage= new myTables(); $myPage->outputTable(); ?> Example Output: <table> <thead> <th>Name</th> <th>MetaValue1</th> </thead> <tbody> <tr><td>Rose</td><td><ul><li>Drinker</li><li>Nice Person</li><li>Runner</li></ul></td></tr> <tr><td>Gary</td><td><ul><li>Player</li><li>Funny</li></ul></td></tr> </tbody> </table> I cut out the Autonum from your query, as it was otherwise buggering up the aggregate function. If you do however need it, you would have to aggregate it in a similar fashion. The group_concat function will skip over null fields, so you will need to bring them in cunningly otherwise your autonum IDs won't match your results. I did this here with a simple coalesce() inside the group_concat function. To accomodate these extra bits, I rewrote the object up somewhat. This should do everything you need, I have left my debugging notes in which are set by the private variable isDebug which I have set to false, but setting it to true will give you extra information as the object runs through the functions. This will help you with your debugging as I assume your source data is actually much more complex. <?php class myUser { public $ID; public $name; public $metaDesc; public $metaNum; public $metaDescs; public $metaNums; } // Basic User stored here. One Object per Row is created. class myTables { private $isDebug=false; // Change this to true to get all validation messages; private $hostname="mysql:host=localhost;dbname=test"; private $username="testdb"; private $password="testdbpassword"; private $myUsers=array(); private $curUser = myUser; private $userCount=0; private $SQL=" select ID, name, GROUP_CONCAT(coalesce(metavalue,'null')) as metaDesc, group_concat(autonum) as metaNum FROM table1 GROUP BY ID, name;"; public function getuserData() { $dbh = new PDO($this->hostname, $this->username, $this->password); $stmt = $dbh->query($this->SQL); $obj = $stmt->setFetchMode(PDO::FETCH_INTO, new myUser); $userCount=0; foreach($stmt as $myUser) { $this->myUsers[$userCount]=new myUser; $this->myUsers[$userCount]->ID=$myUser->ID; $this->myUsers[$userCount]->name=$myUser->name; $this->myUsers[$userCount]->metaDesc=$myUser->metaDesc; $this->myUsers[$userCount]->metaNum=$myUser->metaNum; $userCount++; } $this->userCount=$userCount; if($this->isDebug){echo "There are ".$this->userCount." users found.<br>";} unset($obj); unset($stmt); unset($dbh); } // Pulls the data from the database and populates the this->object. public function outputTable() { echo " <table> <thead> <th>Name</th> <th>MetaValue</th> </thead> <tbody> "; for($i=0; $i<$this->userCount; $i++) { if($this->isDebug){echo "Running main cycle. There are ".$this->userCount." elements.";} $this->myUsers[$i]->metaDescs=explode(',', $this->myUsers[$i]->metaDesc); $this->myUsers[$i]->metaNums=explode(',', $this->myUsers[$i]->metaNum); if($this->isDebug){echo "This user has ".(count($this->myUsers[$i]->metaDescs))." segments<br>";} if($this->isDebug){echo "My first segment is ".($this->myUsers[$i]->metaDesc)."<br>";} echo "<tr><td>".$this->myUsers[$i]->name."</td><td><ul>"; for($j=0;$j<count($this->myUsers[$i]->metaDescs);$j++) { echo "<li>ID: ".$this->myUsers[$i]->metaNums[$j]." - ".$this->myUsers[$i]->metaDescs[$j]."</li>"; } echo "</ul></td></tr>"; } echo " </tbody> </table> "; } // Outputs the data held in the object into the table as required. } $myPage= new myTables(); $myPage->getUserData(); $myPage->outputTable(); ?> The output now looks like this: <table> <thead> <th>Name</th> <th>MetaValue</th> </thead> <tbody> <tr><td>Rose</td><td><ul><li>ID: 1 - Drinker</li><li>ID: 2 - Nice Person</li><li>ID: 3 - Runner</li></ul></td></tr> <tr><td>Gary</td><td><ul><li>ID: 4 - Player</li><li>ID: 5 - Funny</li><li>ID: 6 - null</li><li>ID: 7 - Smelly</li></ul></td></tr> </tbody> </table> Name MetaValue Rose ID: 1 - Drinker ID: 2 - Nice Person ID: 3 - Runner Gary ID: 4 - Player ID: 5 - Funny ID: 6 - null ID: 7 - Smelly
answered Sep 8, 2015 by rajesh
0 votes
You asked how to call this type of problem: Its called grouping. One possibility is indeed to solve it in SQL with the help of the GROUP BY clause (but different SQL engines have varying support for these, especially when it comes to more complex aggregations of the data to be grouped). In C# the basic solution is a one-liner thanks to LINQ, just use the GroupBy extension method: var data = new [] { new { RowId = 1, EmpId = 1, Name = "Rose", Value = "Drinker" }, new { RowId = 2, EmpId = 1, Name = "Rose", Value = "Runner" }, new { RowId = 3, EmpId = 2, Name = "Gary", Value = "Player" }, }; var grouping = data.GroupBy(row => row.Name); var sb = new StringBuilder(); foreach (var grp in grouping) { sb.AppendFormat("<tr><td>{0}</td>\n", grp.Key); sb.AppendLine(" <td><ul>"); foreach (var element in grp) { sb.AppendFormat(" <li>{0}</li>\n", element.Value); } sb.AppendLine(" </ul></td>\n</tr>"); } Console.WriteLine(sb.ToString()); The basic idea behind GroupBy is just some kind of an associative array or dictionary, with the attributes to group by as the key and a list of all rows associated with that key. For example (using the variable data with the above definition): var map = new Dictionary<Tuple<int, string>, List<object>>(); foreach (var row in data) { var key = Tuple.Create(row.EmpId, row.Name); if (!map.ContainsKey(key)) map.Add(key, new List<object>()); map[key].Add(row); } The above snippet is conceptually the same as the PHP based answers from drew010 and invisal (they use a two-dimensional PHP array, which is conceptually the same as above Dictionary of Lists). I tried to make the steps as explicit as possible and not use too much special features of C# (for example in a real program you should tend to use a proper class of its own for complex keys instead of an simple Tuple), so the above snippet should be easily portable to Java and other languages. As you can see by all the examples here, after grouping the data, the HTML generation is always the same (two nested loops).
answered Sep 8, 2015 by rajesh
0 votes
Here is my second approach on the issue, like with the first one, I'm still a fan of solving this with the output, e.g.: <table> <?php foreach($users as $name => $columns) : ?> <tr> <td> <?php echo htmlspecialchars($name); ?> </td> <td> <ul> <?php foreach($columns as $column) : ?> <li><?php echo htmlspecialchars($column); ?></li> <?php endforeach ?> </ul> </td> </tr> <?php endforeach ?> </table> Where as the database result set is here simulated with a array structure but the typical iterator: $rows = array( array(1, 1, 'Rose', 'Drinker'), array(2, 1, 'Rose', 'Nice Person'), array(3, 1, 'Rose', 'Runner'), array(4, 2, 'Gary', 'Player'), array(5, 2, 'Gary', 'Funny'), ); $result = new ArrayIterator($rows); $users = new Users($result); Which demonstrates that this is a single query, no subselects, no re-grouping needed (as outlined in the first question) doing this based on it's order. Only the code for the Users class is missing: class Users extends IteratorIterator { private $last; public function __construct($it) { parent::__construct(new NoRewindIterator($it)); } public function current() { $current = $this->getInnerIterator()->current(); $this->last = $current[2]; return new Columns($this->getInnerIterator(), $this->last); } public function key() { return $this->last; } public function next() { $current = $this->getInnerIterator()->current(); if ($this->last === $current[2] || $current === NULL) { parent::next(); } } } class Columns extends IteratorIterator { private $name; public function __construct($it, $name) { $this->name = $name; parent::__construct($it); } public function valid() { $current = parent::current(); return parent::valid() && $current[2] === $this->name; } public function current() { $current = parent::current(); return $current[3]; } } Full demo at codepad - I must admit this contains a bit of iterator black magic.
answered Sep 8, 2015 by rajesh
0 votes
This would print exactly what you need within the <tbody> tags : <?php $result = mysql_query("SELECT name, metavalue FROM table"); $previous_name = ""; //Variable to keep track of previous name value in array() print '<table><thead><th>Name</th><th>Metavalue</th></thead><tbody>'; //print the static table header while ($row = mysql_fetch_array($result)) { $name = $row['name']; $meta_value = $row['metavalue']; if (($previous_name != $name) && ($previous_name !="")) { //If $name has changed, close tags, reset $previous_name print '</ul></td></tr>'; $previous_name = ""; } if ($previous_name == "") { //New value of $name, open tags, set $name to $previous_name print '<tr><td>'.$name.'</td><td><ul>'; $previous_name = $name; } if ($previous_name == $name) { //print contents of $meta_value if $name is the same print '<li>'.$meta_value.'</li>'; } } //Once there are no more values in the array, close the static table header print '</tbody></table>'; //close the static table header ?>
answered Sep 8, 2015 by rajesh
0 votes
I recommend you to create a function in database create function get_meta(@autonum int) returns varchar(500) as declare @meta varchar(500)='<ul>'; select @meta=@meta+'<li>'+MetaValue+'</li>' from mytable where Autonum=@autonum return @meta+'</ul>'; and use a clean statement in the PHP side like this. select id,autonum,name, get_meta(autonum) as meta_output from mytable then you need to do the echo $row["meta_output"]; like any other column. This is what I would use.
answered Sep 8, 2015 by rajesh
0 votes
This is pretty close to some of the other responses, but I think a bit cleaner and easier to follow. I create a 3 dimensional array prior to any output for ease of use. You could do everything at once, but I find that cleaner looking code tends to separate it (reading from the database is different than outputting, for example, so keep them separate). This way you also have a handy array if you ever need to reference person 33's 15th metavalue $resultArr[33]["meta"][15]. I also added class names and an ID for each result row for easy CSS styling. <?php // DB connect // // Get the DB Data $result = mysql_query("SELECT Autonum, ID, Name, MetaValue FROM table GROUP BY ID"); // Set Start Values $resultArr = array(); $curRow = -1; $curMeta = -1; // Loop Through the Rows while ($row = mysql_fetch_assoc($result)) { // Start of a new ID, Set the name and Create the MetaValue Array if ($curRow != $row["ID"]){ $curRow = $row["ID"]; $resultArr[$curRow]["name"] = $row["Name"]; $resultArr[$curRow]["meta"] = array(); $curMeta = 0; } // Add the MetaValue $resultArr[$curRow]["meta"][$curMeta] = $row["MetaValue"}; $curMeta++; } /* Array looks like: $resultArr[1]["name"] = "Rose"; $resultArr[1]["meta"][0] = "Drinker"; $resultArr[1]["meta"][1] = "Nice Person"; $resultArr[1]["meta"][2] = "Runner"; $resultArr[2]["name"] = "Gary"; $resultArr[2]["meta"][0] = "Player"; $resultArr[2]["meta"][1] = "Funny"; */ // Start the Table $out = "<table>"; $out .= "\n<thead>"; $out .= "\n<th>Name</th>"; $out .= "\n<th>MetaValue1</th>"; $out .= "\n</thead>"; $out .= "\n<tbody>"; // Add the Rows foreach($resultArr as $id => $col){ $out .= "\n\n<tr id='result_" . $id . "'>"; $out .= "\n<td class='rowName'>" . $col["name"] . "</td>"; $out .= "\n<td class='rowMeta'>"; $out .= "\n<ul>"; foreach($col["meta"] as $meta){ $out .= "\n<li>".$meta."</li>"; } $out .= "\n</ul>"; $out .= "\n</td>"; $out .= "\n</tr>"; } // Close the Table $out .= "\n</tbody>"; $out .= "\n</table>"; // Print It Out Where You Need It echo $out; ?>
answered Sep 8, 2015 by rajesh
0 votes
Iam here neither grouping on MySql or PHP side,i.e not using the memory of php for grouping or using the mysql function. Just having control over printing. You can see the working example of the below code here <?php $result = mysql_query("SELECT name,metavalue FROM table"); $count = mysql_num_rows($result); ?> <table> <thead> <th>Name</th> <th>MetaValue1</th> </thead> <tbody> <?php $i = 0; // loop through each row $start = 1; while ($row = mysql_fetch_assoc($result) { if ($name != $row['name']) {// row with new name if ($start) { $start = 0; echo "<tr>"; echo "<td>" . $row['name'] . "</td> <td><ul><li>" . $row['metadata'] . "</li>"; } else { $start = 1; echo "</ul></td>"; echo "</tr><tr>"; echo "<td>" . $row['name'] . "</td> <td><ul><li>" . $row['metadata'] . "</li>"; } } else {//row with the same name echo "<li>" . $row['metadata'] . "</li>"; if ($i == $count - 1) { echo "</ul></td></tr>"; } } ?> <?php $name = $row['name']; $i++; } ?> </tbody> </table>
answered Sep 8, 2015 by rajesh
0 votes
Here is the code for you want. To avoid any conflict with your code i am not using any class object concept, hence code is written in simple way. It look in simple fashion but it is working no doubt. Note that code is placed by senior programmer working in php for last one and half year. so dont mind the simple fashion of the code <table> <thead> <th>Name</th> <th>MetaValue1</th> </thead> <tbody> <?php mysql_select_db("dbName", $con); $result = mysql_query("SELECT DISTINCT Name,ID FROM tableName"); while($row = mysql_fetch_array($result)) { $userName = $row['Name']; echo $userId = $row['ID']; ?> <tr> <td><?=$userName?> <?=$userId?></td> <td> <ul> <?php $resultNew = mysql_query("SELECT * FROM tableName WHERE ID =$userId"); while($row = mysql_fetch_array($resultNew)) { $mValue = $row['MetaValue']; ?> <li><?=$mValue?></li> <?php } ?> </ul> </td> </tr> <?php } ?> </tbody> </table>
answered Sep 8, 2015 by rajesh
0 votes
<?php /** * Displaying a table in PHP with repeated columns * @link a/11616884/367456 */ class Events { private $row = 0; public function newRow($name) { $this->closeRow(); echo " <tr><td>$name</td><ul>"; $this->row++; } public function closeRow() { if (!$this->row) return; echo "</ul></tr>\n"; $this->row = 0; } public function newItem($name) { echo "<li>$name</li>"; } } $rows = array( array(1, 1, 'Rose', 'Drinker'), array(2, 1, 'Rose', 'Nice Person'), array(3, 1, 'Rose', 'Runner'), array(4, 2, 'Gary', 'Player'), array(5, 2, 'Gary', 'Funny'), ); echo "<table>\n <thead>\n <th>Name</th>\n <th>MetaValue1</th>\n </thead>\n <tbody>\n"; $events = new Events(); $last = null; foreach ($rows as $row) { if (@$last[2] !== $row[2]) { $events->newRow($row[2]); } $events->newItem($row[3]); $last = $row; } $events->closeRow(); echo " </tbody>\n</table>";
answered Sep 8, 2015 by rajesh

...