Join two MySQL tables and group result with php - php

I have the following code to populate cities in a table.
$cities_query = "SELECT city_name FROM city_selection";
$cities_result = mysql_query($cities_query);
echo "<table>";
while ($row = mysql_fetch_assoc($cities_result))
{
echo "<tr>";
echo "<td>".$row['city_name'] . "</td>";
echo "</tr>";
}
echo "</table>";
Now I need to group every city by a region so I created the table called city_region_selection and added a Foreign key from the new column "region_id" in the city_selection table to region_id in the new table.
I'm now struggling to present this data in a nice html table using PHP.
Is it even possible to populate first a table row with region_name and then some subrows containing cities from that region? Please see this image for details:

You just have to do a little preprocessing:
/* SQL
SELECT
city_name,
region_name
FROM
city_selection
NATURAL JOIN city_region_selection
SQL */
$regions = array();
while ($result->fetch()) {
if (!isset($regions[$result->region_name])) {
$regions[$result->region_name] = array();
}
$regions[$result->region_name][] = $result->city_name;
}
Alternate Method with SQL focus
/* SQL
SELECT
region_name,
GROUP_CONCAT(city_name SEPARATOR ',') cities
FROM
city_selection
NATURAL JOIN city_region_selection
GROUP BY
region_name
*/
$regions = array();
while ($result->fetch()) {
$regions[$result->region_name] = explode(',', $result->city_name);
}
Help
Note that the while syntax is just abridged. You would probably replace it with
while ($row = mysql_fetch_assoc($cities_result)) {
$regions[$row['region_name']] = explode(',', $row['city_name']);
}
... for example
Once regions is built, simply do this:
foreach ($regions as $region => $cities) {
echo "<tr><td>$region</td></tr>";
foreach ($cities as $city) {
echo "<tr><td class="tabbed">$city</td></tr>";
}
}

Related

Loop through one table with another loop for each record

I have one table with categories and another table with linkrecords for each category and the table structure looks like this:
categories:
id (int)
name (varchar)
links:
id (int)
link (varchar)
fk_cat_id (int)
Here is how I do now, but know that it is a no go with a query within a query:
$query = "SELECT * FROM categories";
if ($result = $mysqli->query($query)) {
while ($row = $result->fetch_assoc()) {
$catid = $row['cat_id'];
echo 'CatName: '.$row['name'];
echo '<ul>';
$query2 = "SELECT * FROM links WHERE fk_cat_id = $catid";
if ($result2 = $mysqli->query($query2)) {
while ($row2 = $result2->fetch_assoc()) {
echo '<li>'.$row2['link'].'</li>';
}
}
echo '</ul>';
}
}
I guess I have to go to some JOIN method, but not sure how!
Following query will be used to retrieve links with relation to link categories.
Also, It is a good practice to specify fields name in query to retrieve specific columns only instead of *.
SELECT links.id AS link_id, links.link, links.fk_cat_id, categories.name
FROM links
JOIN categories ON categories.id = links.fk_cat_id;

for each statement only returns the word 'Array'

I'm creating a personal advisor page with 3 advisors in my database, I'm trying to create a dropdown box where someone can choose which advisor they'd like. At the moment my dropdown only displays the word 'Array' three times. Here's what I have so far.
<select name="advisor">
<?
$sqlQ = "SELECT concat(firstName,' ',lastName) FROM adv WHERE advisor IS NULL";
$array=array();
$res = $db->prepare($sqlQ);
$res->execute();
echo("<option>Advisor</option>");
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
$array[] = $row;
}
foreach($array as $info)
{
echo("<option>$info</option>");
}
Your $row is already an array, so no need to insert your $row into a new array. Just loop the results like this
while ($row = $result->fetch(PDO::FETCH_ASSOC))
{
foreach($row as $info)
{
echo("<option>$info</option>");
}
}
// give the result of concat() an alias so you can easily access it in the result set
$sqlQ = "SELECT concat(firstName,' ',lastName) as name FROM adv WHERE advisor IS NULL";
[...]
while ( $row = $result->fetch(PDO::FETCH_ASSOC) ) {
// $row is an array, its members correspond with the fields/aliases you've selected
// apply htmlspecialchars() so that the contents of $row['name'] can't break your html structure
echo '<option>', htmlspecialchars($row['name']), '</option>';
}

Grouping row elements into one column using SQL

My current table is fetching content from the database like this but I would like to combine the rows so that all the Room Preference's are displayed in one row rather than over several. How can I go about doing this? As a result the table below would have only two rows.
The Room Preference information is being inferred from ts_roompref.
Here is my code so far:
$sql = "SELECT
*
FROM ts_request
INNER JOIN ts_day
ON ts_request.day_id = ts_day.id
INNER JOIN ts_period
ON ts_request.period_id = ts_period.id
INNER JOIN ts_allocation
ON ts_request.id = ts_allocation.request_id
INNER JOIN ts_roompref
ON ts_request.id = ts_roompref.request_id
WHERE ts_request.round=:round
AND ts_request.dept_id=:dept
ORDER BY ts_request.module_id ASC";
}
$stm = $pdo->prepare( $sql );
$stm->execute( array( ':round' => 'P', ':dept' => $loggedin_id ) );
$rows = $stm->fetchAll();
foreach ($rows as $row)
{
echo '<tr align="center">';
echo '<td>'.$row['module_id'].'</td>';
echo '<td>'.$row['day'].'</td>';
echo '<td>'.$row['period'].'</td>';
echo '<td>';
if ($row['room_id']=="0")
{
echo "Any";
}
else
{
echo $row['room_id'];
}
echo '</td>';
echo '<td>'.$row['status'].'</td>';
echo '</tr>';
Well, I guess your trying to do it in SQL, but if you wanted to do it in your PHP you could loop over the rows watching for changes to Module Code. Pseudo code something like...
$newrows = array()
$tmpCode = ""
foreach $rows as $row
if $tmpCode != $row['module_code'] {
$tmpCode = $row['module_code']
$newrows[] = $row
} else {
$newrows[count($newrows) - 1]['room_preference'] .= $row['room_preference']
}
}
...rough, but you get the idea.
If you want to do it in SQL, can't you do a GROUP_CONCAT on room_preference and GROUP BY the other 4 fields?

while (double?) foreach or join?

I have an Excel sheet which is converted to csv and then code imports that into mysql.
In Excel I have in first row A's and B's
I get output, It works but I cannot get into displaying data right.
How I'm trying to display is A B then break and again A B and so on. It is ordered by contact_id but I only get AAAAAA's and 1 B if I try double while.
This is the code with which I have tried to achieve this. Tried double while and I have googled and I have noticed double while is not working, Couldn't get it to work with mysql JOIN either and have never worked with foreach function.
$data = dbquery("SELECT contact_id, contact_first, contact_last, contact_email FROM contact_info WHERE contact_first='A)' ORDER BY contact_id ASC");
$data2 = dbquery("SELECT contact_id, contact_first, contact_last, contact_email FROM contact_info WHERE contact_first='B)' ORDER BY contact_id ASC");
while ($userdata = dbarray($data)) {
echo "<li><ul class='ulcla'>";
echo "<h1>".$userdata['contact_first']."</h1>";
echo "<li>".$userdata['contact_last']."</li>";
echo "</ul><br>";
while ($userdata = dbarray($data2)) {
echo "".$userdata['contact_id']." - ".$userdata2['contact_first']." - ".$userdata2['contact_last']." - ".$userdata2['contact_email']."";
echo "<br>";
}
echo "</ol></div>";
}
How could I loop data like that?
Change while ($userdata = dbarray($data2)) { to while ($userdata2 = dbarray($data2)) {for innner while loop
$data = dbquery("SELECT contact_id, contact_first, contact_last, contact_email FROM contact_info WHERE contact_first='B)' ORDER BY contact_id ASC");
$data2 = dbquery("SELECT contact_id, contact_first, contact_last, contact_email FROM contact_info WHERE contact_first='B)' ORDER BY contact_id ASC");
while ($userdata = dbarray($data)) {
echo "<li><ul class='ulcla'>";
echo "<h1>".$userdata['contact_first']."</h1>";
echo "<li>".$userdata['contact_last']."</li>";
echo "</ul><br>";
while ($userdata2 = dbarray($data2)) {
echo "".$userdata2['contact_id']." - ".$userdata2['contact_first']." - ".$userdata2['contact_last']." - ".$userdata2['contact_email']."";
echo "<br>";
}
echo "</ol></div>";
}
If there are the same amount of each A and B then you can create two arrays from the output and use a simple for loop to go through the keys. So it could echo $userdata[$x] and $userdata2[$x] where $x is the loop iterator.
Try to avoid using multiple loops, especially nested loops.
while ($userdata = dbarray($data)) {
//your stuff
while ($other_userdata = dbarray($data2)) {
//your other stuff
}
}

Getting the table name of a row from a mysql query that grabs from multiple tables

I have some PHP/MySQL code that pulls data from multiple different tables (using Inner Joins). It looks something like this:
$query = "SELECT * FROM table1 INNER JOIN table2 USING (key)";
$data = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_array($data)) {
echo $row[1];
}
So the code is simple enough, but what I want to do is echo the table each row is in inside of that while loop, since it could be in one of 2 tables.
I saw there was some old mysql functions like mysql_field_table and mysql_tablename that would do the trick, but they all seem to be deprecated.
Would appreciate any advice on how to accomplish this.
You could select the data with a special identifier for each table instead of using *
select table1.row1 as t1r1, table2.row1 as t2r1,..... from .....
And inside php you could look for the strings t1 and t2 and do stuff accordingly.
What you can do is echo more than one field from your result table (which hopefully now contains information from both the tables.
$query = "SELECT * FROM table1 INNER JOIN table2 USING (key)";
$data = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_array($data))
{
echo $row[1] . " " . $row[2];
}
...and then $row[3] etc...
Or access the column name/field by the column name or alias provided by AS.
$query = "SELECT * FROM table1 INNER JOIN table2 USING (key)";
$data = mysqli_query($dbc, $query);
while ($row = mysqli_fetch_assoc($data))
{
echo $row["c_name1"] . " " . $row["c_name2"];
}
Where "c_name1" and "c_name2" are your column names.
Use an AS keyword to rename all columns.
$select_clause = '';
$tables = array('tblA', 'tblB');
foreach($tables as $tbl) {
mysql_query('SHOW COLUMNS FROM ' . $tbl);
while ($row = mysql_fetch_assoc())
$select_clause .= '`'.$tbl.'`.`'.$row['Field'].'` AS `'.$tbl
.'_'.$row['Field'].'`,';
}
$select_clause = substr($select_clause, 0, -1);
mysql_query('SELECT '.$select_clause.' FROM /*...*/ ');

Categories