I've got a piece of coursework to build a php site using mysql.I need to be able to sort a table of data based on it's columns. The data is retrieved from a mysql DB using PDO. I then just echo a table while looping through each row of data
Any Ideas as to how I can sort the data by columns? Preferably I'd like to be able to sort the data (ascending) by clicking on the table headers. But i'm open to Ideas.
Code Below:
PHP:
function displayBooks($data){
echo "<table id= \"allBooks\">";
echo "<th>Book ID</th><th>Title</th><th>Description</th><th>In Stock</th><th>Price</th><th>Cateogry</th>";
#foreach($data as $row)
{
echo "<tr>";
echo "<td>".$row['bookID']."</td>";
echo "<td>".$row['title']."</td>";
echo "<td>".$row['description']."</td>";
echo "<td>".$row['quantity']."</td>";
echo "<td>£".$row['price']."</td>";
echo "<td>".$row['name']."</td>";
echo "</tr>";
}
echo "</table>";
....
//Retrieve all books
$all_books_query = "SELECT b.bookID,b.title,b.description,b.quantity,b.price,c.name FROM Books b
INNER JOIN Book_Category bc ON bc.bookID = b.bookID
INNER JOIN Category c ON c.catID = bc.catID
GROUP BY b.bookID;";
$rows = $db->query($all_books_query)->fetchAll();
I've got a whole lot more PHP in the rest of the page. Not sure what else I need to include in this to make more sense of the problem, but any ideas will help.
Set up a mechanism to send the user's sorting requirements back to the server (query param? post?), and use those requirements to set up an ORDER BY clause in your MySQL query.
Here's a simple, non_robust implementation
You must make some active links, with params, like this:
function displayBooks($data){
echo "<table id= \"allBooks\">";
echo "<th><a href='index.php?col=1&order_by=1'>Book ID ASC</a>|<a href='index.php?col=1&order_by=2'>Book ID DESC</a></th><th><a href='index.php?col=2&order_by=1'>Title ASC</a>|<a href='index.php?col=2&order_by=2'>Title ID DESC</a></th>";
#foreach($data as $row)
{
echo "<tr>";
echo "<td>".$row['bookID']."</td>";
echo "<td>".$row['title']."</td>";
echo "</tr>";
}
echo "</table>";
And the second poart of script
//Retrieve all books
$order_by = 'ASC';
switch ( (int)$_GET['order_by'] ) {
case 1:
$order_by = 'ASC';
break;
case 2:
$order_by = 'DESC';
break;
}
$col= "bookID";
switch ( (int)$_GET['col'] ) {
case 1:
$col = 'bookID';
break;
case 2:
$col = 'title';
break;
}
$all_books_query = "SELECT b.bookID,b.title,b.description,b.quantity,b.price,c.name FROM Books b
INNER JOIN Book_Category bc ON bc.bookID = b.bookID
INNER JOIN Category c ON c.catID = bc.catID
GROUP BY b.bookID
ORDER BY $col $order_by";
$rows = $db->query($all_books_query)->fetchAll();
Related
I want to return to the user a table that shows his orders but when a user orders one product the table is ok but in the moment that orders 2 product they get 2 lines with the same ID but different ProductID same total price.
$email = strval($_SESSION["email"]);
$TabellaOrdini = "SELECT DISTINCT ordini.IDOrdini, clienti.Indirizzo,
clienti.Nome, clienti.Cognome, ordini.StatoConsegna,
prodotti.Descrizione, ordini.TotaleOrdine,
pacco.IDProdotti, pacco.Quantita
FROM (((clienti NATURAL JOIN ordini)
JOIN pacco ON ordini.IDPacco = pacco.IDPacco)
JOIN prodotti ON pacco.IDProdotti = prodotti.IDProdotti)
WHERE clienti.IDClienti = ordini.IDClienti
AND clienti.Email = '$email'
ORDER BY ordini.IDOrdini";
$CheckOrdini = "SELECT insertphpordini.IDOrdini,
concat(insertphpordini.Descrizione,' x ',insertphpordini.Quantita) AS Risultato
FROM insertphpordini
WHERE insertphpordini.Email = '$email'
AND insertphpordini.IDOrdini IN
( SELECT insertphpordini.IDOrdini
FROM insertphpordini
GROUP BY insertphpordini.IDOrdini
HAVING COUNT(IDOrdini)>1
)";
$result = $conn -> query($TabellaOrdini);
$result2 = $conn -> query($CheckOrdini);
echo "<table id='customers'>";
echo "<tr><th colspan=7>Ordini</th></tr>";
echo "<tr>";
echo "<td><b>IDOrdine</b></td>";
echo "<td><b>Nome</b></td>";
echo "<td><b>Cognome</b></td>";
echo "<td><b>Indirizzo</b></td>";
echo "<td><b>Stato Consegna</b></td>";
echo "<td><b>Prodotto</b></td>";
echo "<td><b>Totale Ordine</b></td>";
while($row = $result -> fetch_assoc()) {
echo "<tr>";
echo "<td> $row[IDOrdini]</td>";
echo "<td> $row[Nome]</td>";
echo "<td> $row[Cognome] </td>";
echo "<td> $row[Indirizzo] </td>";
echo "<td> $row[StatoConsegna] </td>";
echo "<td> $row[Descrizione] / $row[Quantita]</td> ";
echo "<td> $row[TotaleOrdine]€ </td>";
echo "</tr>";
}
echo "</table>";
the query $TabellaOrdini get all values from a user whit that email and the query $CheckOrdini get only the values with the same ID and concat the Description and quantity as Risultato.
My goal is that is possible to have 1 order with 1 ID and in Product(row 6 from left of the table) have "ProductName1/Quantity1, ProductName2/Quantity2"
Use GROUP_CONCAT() to combine values from multiple rows into a single column.
$TabellaOrdini = "SELECT ordini.IDOrdini, clienti.Indirizzo, clienti.Nome, clienti.Cognome, ordini.StatoConsegna,
prodotti.Descrizione, ordini.TotaleOrdine, GROUP_CONCAT(pacco.IDProdotti, '/', pacco.Quantita) AS Prodotto
FROM clienti
NATURAL JOIN ordini
JOIN pacco ON ordini.IDPacco = pacco.IDPacco
JOIN prodotti ON pacco.IDProdotti = prodotti.IDProdotti
WHERE clienti.IDClienti = ordini.IDClienti AND clienti.Email = '$email' ORDER BY ordini.IDOrdini
GROUP BY ordini.IDOdini";
It's also not necessary to group your joins with ().
And you should stop substituting variables directly into SQL, and instead use prepared statements with bind_param().
You can use better display of Orders with Order ID, Customer details, Date in one row along with a drop down with all detailed products and quantities. This way you are not limited with tabular display option.
Else, you can use GROUP_CONCAT with ordini.IDOrdini (your OrderID) and display products as "product01, product02, product03" for same Order01 for instance.
Here some link for data-tables with child-rows :
https://datatables.net/examples/api/row_details.html
Or you can ajax it out for large child product sets :
https://datatables.net/blog/2017-03-31
NOTE: Please ensure PHP security and try to follow some design pattern for a clean code. Look for Database Object and Binding input parameters with $conn->prepare [https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php]
I have to check if a value is present in two tables, through a left join, if there is a relationship write yes, otherwise no
every time I associate an evidence (tev_Evidenze) to the structure (tev_Tipi_accreditamento) the query should tell me for that structure there is evidence, only now at structure n6. no evidence is present and anyway I answer yes
code:
<?php
$CONTROLLA = mysqli_query($riskmanagement,
"SELECT * FROM tev_Tipi_accreditamento LEFT JOIN tev_Evidenze
ON tev_Tipi_accreditamento. ID_tipo_acc = tev_Evidenze.id_tipo_accreditamento
WHERE tev_Tipi_accreditamento.id_struttura = tev_Evidenze.id_struttura GROUP BY tev_Evidenze.id_struttura");
$EVIDENZE=mysqli_num_rows($CONTROLLA);
if($EVIDENZE==0) {
echo "SI";
}else{
echo "no";
}
?>
The cycle is correct I am sure that in the db, there are no values present in both tables but my if does not seem to work
NOTE:
<?php
$query_string = "SELECT * FROM tev_Tipi_accreditamento LEFT JOIN tev_Evidenze
ON tev_Tipi_accreditamento. ID_tipo_acc = tev_Evidenze.id_tipo_accreditamento
WHERE tev_Tipi_accreditamento.id_struttura = tev_Evidenze.id_struttura GROUP BY tev_Evidenze.id_struttura";
$query = mysqli_query($riskmanagement, $query_string);
?>
<?php
while($row = mysqli_fetch_assoc($query)){ ?>
<?php echo $row['id_struttura'] ;
if($query_string==0) {
echo "SI";
}else{
echo "no";
}?>
<?php } ?>
You're counting ALL the matches, not the number of matches for each structure. You can use the following:
SELECT s.id_struttura, IF(COUNT(e.id_struttura) > 0, 'Yes', 'No') AS matches
FROM tev_Tipi_accreditamento AS s
LEFT JOIN tev_Evidenze AS e ON s.id_struttura = e.id_struttura AND s.ID_tipo_acc = e.id_tipo_accreditamento
GROUP BY s.id_struttura
This will return a table like:
1 Yes
2 No
3 No
4 Yes
for each structure ID.
DEMO
You can show the result with:
$CONTROLLA = mysqli_query($riskmanagement, "
SELECT s.id_struttura, IF(COUNT(e.id_struttura) > 0, 'Yes', 'No') AS matches
FROM tev_Tipi_accreditamento AS s
LEFT JOIN tev_Evidenze AS e ON s.id_struttura = e.id_struttura AND s.ID_tipo_acc = e.id_tipo_accreditamento
GROUP BY s.id_struttura") or die(mysqli_error($riskmanagement));
echo "<table>";
while ($row = mysqli_fetch_assoc($CONTROLLA)) {
echo "<tr><td>{$row['id_struttura']}</td><td>{$row['matches']}</td>
}
echo "</table>";
I have table product and table category in my database. I want to display all category dynamically in a table and inside the table of each category I am displaying all item belonged to that category too.
Those categories and items should be displayed like this :
And here is my coding to do the work :
$fetch_cat = "SELECT * FROM tblcat"; //fetch from table category
$result = $conn->query($fetch_cat);
if ($result->num_rows > 0)
{
while($cat_row = mysqli_fetch_assoc($result))
{
$cat_title = $cat_row['catName'];
echo '<table>';
echo '<tr>';
echo '<td><img src="category/'.$cat_row['catImg'].'" /></td>';
echo '<td>';
echo '<ul class="content_init">';
$stmt = "SELECT * FROM tblproduct WHERE prodCat = '".addslashes($cat_title)."' LIMIT 4"; //fetch from table product
$result = $conn->query($stmt);
if ($result->num_rows > 0)
{
while($row = mysqli_fetch_assoc($result))
{
echo '<li>';
echo '<a href="#"><img style="height: 188px; width: 188px;" src="user_images/'.$row['prodImg'].'" />';
echo '<br /><br />';
echo '<h4>'.$row['prodName'].'</h4>';
echo '<label><span>RM </span>'.$row['prodPrice'].'</label></a>';
echo '</li>';
}
}
echo '</ul>';
echo '</td>';
echo '</tr>';
echo '</table>';
}
}
Problem :
So the problem with my coding is, it can only display Category 1 with items belonged to it. The rest categories unable to be displayed. I guess my coding might not loop properly because of bad programming as it unable to display the expected output.
The $result variable was reused by the inner query thus the first result override.
Change the variable name either of the $result variable.
$result1 = $conn->query($stmt);
if ($result1->num_rows > 0)
{
while($row = mysqli_fetch_assoc($result1))
{
Your approach is not good/optimal. You have query for the categories and then one query per each category,so if you have 10 categories your code would execute 11 queries. You should do it with one query only using INNER JOIN
You can select all the values left joining the category table for the names and group them by their category ID.
See Group array by subarray values
Afterwards, you can traverse each product for each category by accessing the subarrays.
I'm tired of searching for the solution my news comment system.
What i have.
I have 2 different mysql tables item (id, title, category_id, details) and comments (id, item_id, comment)
If i have single news then counting is fine like here in picture:
Single news
Code:
if (!empty($comments)) {
$comm = count($comments);
} else {
$comm = 0;
}
But if i use same code category view, result is:
Category view
If i use code:
$sqls = mysql_query("SELECT c.item_id,
COUNT(c.comment)
FROM comments c
RIGHT JOIN items i
ON c.item_id = i.id
GROUP BY c.item_id");
$comm = mysql_num_rows($sqls);
$smarty->assign('comm',$comm);
Result is :Some number of comments
How to make possible to see the Category View the correct number of comments?
TRY this example. The result is the same as the screenshot below but with some background colour to distinguish the difference. Of course you should change to your own connection and layout.
<?php
$db = new PDO('sqlite:news.db');//change to your own
$sql = $db->prepare("
SELECT item.id, item.title, item.details, comments.comment, COUNT(comments.id) AS NumberOfComment
FROM item LEFT JOIN comments ON item.id = comments.item_id
GROUP BY item.id ORDER BY item.id");
$sql->execute();
$row = $sql->fetchAll();
//get comment
$comment = $db->prepare("SELECT comment FROM comments WHERE item_id = ?");
foreach ($row as $rows){
echo "<br>";
echo "Title: ".$rows['title'];
echo "<br>";
echo "Details: ".$rows['details'];
echo "<br>";
echo "<i>".$rows['NumberOfComment']." comments </i>";
echo "<br>";
$comment->execute(array($rows['id']));
$comments = $comment->fetchAll();
echo '<div style="background-color:pink;">';
foreach ($comments as $showcomment){
echo $showcomment['comment'];
echo "<br>";
}
echo "</div>";
echo "<br>";
}
?>
example item table
example comment table
and the result is...
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?