How to show data from two tables php mysql by avoiding repeats? - php

Here is what i am doing I have two tables one is categories and other is softwares
Category table Looks like this
cid name
1 Anti-malware
And Software Table looks like this
id title catid
1 Avast 1
And catid is equal cid you can say that catid is id of category
here is my current code
require('config/db.php');
$cateq="SELECT * FROM softwares A INNER JOIN categories B ON A.catid=B.cID ";
$cateresult=mysql_query($cateq);
define('MAX_TITLES_PER_CAT',5);
$cat='';
$tcount=0;
while ($row =mysql_fetch_array($cateresult)){
$title=$row['title'];
$softid=$row['id'];
$cateid=$row['cid'];
$check_pic = "admin/images/icons/".$softid."/image01.jpg";
if (file_exists($check_pic)) {
$icon = "<img src=\"$check_pic\" class=\"home_icon\" />";
} else {
$icon = "<i class=\"icon-archive\"></i>";
}
if ($row['name']!=$cat) {
if ($cat!='') echo '</div>';
$cat=$row['name'];
$tcount=MAX_TITLES_PER_CAT;
echo "<div class=\"widget white_box\"><h3 class=\"widget_title\">".$cat." <i class=\"icon-chevron-right\"></i></h3><ul>";
}
if ($tcount--<=0) continue;
echo '<li>'.$icon.' <a href=\'software-profile.php?pid='.$softid.'\'>'.$title.'</a></li>';
}
if ($cat!='') echo '</ul></div>';
and here are the results what i am getting
http://postimg.org/image/d7zn2k6ev/full/
its repeating certain categories in different divs instead of showing in same div all the results.

When you parse your query results, you assume the rows are sorted by category (if ($row['name']!=$cat)), but no order is guaranteed without an ORDER BY clause.
Add ORDER BY name to the end of your query.

Related

Updating query to reflect normalized database

I am trying to make an article website, but I want to normalize my current database. I have four tables each labeling a category except for one. The four tables are: Entertainment, Lifestyle, Science, and Articles. Articles is the combination of all the entries of Entertainment, Lifestyle, and Science. I want to delete Entertainment, Lifestyle, and Science and just leave the Articles table, thus saving space and increasing performance. The only problem I am facing though is with a query that generates random articles by getting the last ID of the table, and then getting a random number between 6 and the max ID.
All my tables have the following structure: id (unique), category (the type of article this is, i.e Entertainment), title (title of the article), image (image URL of the article), link (URL of the article), Counter (number of views this article has), and dateStamp (the date the article was published). Here's the query I am trying to update based on my normalized database.
<?php
//SELECT the MAX id from the Entertainment table
$MAX_ID = $db->query("SELECT MAX(id) FROM Entertainment");
//Get Max id value
$MAX_ID = $MAX_ID->fetch_array();
$MAX_ID = $MAX_ID[0];
//Create random number variable
$RAND_NUM;
//If the Max ID is less than 6, make $MAX_ID the $RAND_NUM
if ($MAX_ID < 6) {
$RAND_NUM = $MAX_ID;
}
//Else get a random value between 6 and the Max ID
else {
$RAND_NUM = mt_rand(6, $MAX_ID);
}
//Grab 6 articles by descending from the random number, example: If $RAND_NUM is 7, get all entries from 7-2
$resultSet = $db->query("SELECT * FROM Entertainment WHERE id <= $RAND_NUM ORDER BY id DESC LIMIT 6");
if ($resultSet->num_rows != 0) {
//Booleans to check where we are at in the print off
$conditional = true;
$conditional2 = true;
echo "<div class='row'>";
while ($rows = $resultSet->fetch_assoc()) {
$image = $rows["image"];
$title = $rows["title"];
$link = $rows["link"];
$count = number_format($rows["Counter"]);
//Print off these articles on the left
if ($conditional == true && $conditional2 == true) {
echo "<div class='left'><a href='$link'><img src=$image><p>$title</p></a><p id='article-views'><span class='glyphicon glyphicon-fire'></span> $count Views</p></div>";
$conditional2 = false;
}
//Print off these articles on the right
else {
echo "<div class='right'><a href='$link'><img src=$image><p>$title</p></a><p id='article-views'><span class='glyphicon glyphicon-fire'></span> $count Views</p></div><hr>";
$conditional2 = true;
}
}
echo "</div>";
}
?>
How should I change/update this query to make it so that I get random Entertainment articles from the Articles table? I am open to any changes that improve the performance of the query as well.
Instead of selecting a random ending ID, just randomize all the rows and select 6 from them.
SELECT *
FROM Articles
WHERE category = 'Entertainment'
ORDER BY RAND()
LIMIT 6
If you need to avoid ORDER BY RAND() because it doesn't perform well enough, see How can i optimize MySQL's ORDER BY RAND() function?

Display all pages under categories in PHP with joins

I have 2 tables. The first one, pages, contains a foreign key category_id and the other table, categories, contains an id and a title field.
Here is my sql query :
SELECT categories.title as titleCategory, pages.title as titlePage FROM categories INNER JOIN pages ON pages.category_id = categories.id ORDER BY categories.title
What is want is to display the pages and categories like this :
category 1
page 1
page 2
category 2
page 1
etc...
Is there a way to do that using a foreach or do I have to use 2 queries?
Thank you very much for your help.
Assuming PHP, but the logic shoudl work in any language.
$cur_cat = null;
foreach($results as $result){
if($cur_cat != $result['titleCategory']){
echo $result['titleCategory'];
}
$cur_cat = $result['titleCategory'];
echo $result['titlePage'];
}
Just put a check in the single foreach loop.
$currentCategory = null;
foreach( $results as $result ) {
if( $currentCategory != $result['titleCategory'] ) {
$currentCategory = $result['titleCategory'];
echo $result['titleCategory'];
}
echo $result['titlePage'];
}
This will only print out the title if it has changed. You already have the, ordered by categoryTitle so if the category doesn't change it will only print the pageTitle.

Search multiple tables and display links to different files

I have 2 tables first one tblactive ( ac_id, ac_title, ac_text) , second one tblnews (n_id, n_title, n_text)
Also I have 3 files
Active.php (in this file I obtain data from table active and display it through function displayac, ex. <a href=active.php?op=displayac&ac_id=$ac_id>$ac_title</a>)
News.php (in this file I obtain data from table news and display it through function displaynews, ex. <a href=news.php?op=displaynews&n_id=$n_id>$n_title</a>)
The problem
Search.php ( in this file I want to search the (searchword like ac_text and searchword like n_text in the 2 tables active & news at same time and display result of search containing links to their original files ex.
This my query
$result ="(select n_title,n_text, n_id from tblnews where n_text LIKE '%$searchword%')
union
(select ac_title,ac_text, ac_id from tblactive where ac_text LIKE '%$searchword%') limit $page, $perpage";
$query=mysql_query($result);
If the searchword found in ac_text column the link will be <a href=active.php?op=displayac&ac_id=$ac_id>$ac_title</a>
And if searchword found in n_text column the link will be <a href=news.php?op=displaynews&n_id=$n_id>$n_title</a>
Union will not tell you from which table the data came, so manipulate your query as
(select n_title,'n' as wchtab, n_text, n_id from tblnews where n_text LIKE '%e%')
union
(select ac_title,'a' as wchtab, ac_text, ac_id from tblactive where ac_text LIKE '%e%')
where 'wchtab' tells you from which table the data came from, now you can check while fetching the records like
while ($row = mysql_fetch_assoc($result)) {
if($row['wchtab'] == 'n'){
$n_title = $row['N_TITLE'];
$n_id = $row['N_ID'];
echo "<a href=news.php?op=displaynews&n_id=$n_id>$n_title</a>"
}
else if($row['wchtab'] == 'a'){
$ac_title = $row['N_TITLE'];
$a_id = $row['N_ID'];
echo "<a href=active.php?op=displayac&ac_id=$ac_id>$ac_title</a>";
}
NOTE as you are using union, you will get the title of the column as the first table name column fields, so you won't get ac_title separately, but the column n_title will hold data for ac_title and wchtab will tell you from which table the data has came.
}

Echo all results from sql join when using group by

I have the following query which I run via PHP:
select
{$tableProducts}.*,
{$tableImages}.*
from {$tableProducts}
left join {$tableImages}
on {$tableImages}.product_id = {$tableProducts}.product_id
group by {$tableProducts}.product_id;
Each product (from product table) can have several images (in images table). I loop through the results with a simple while statement:
while($row = $results->fetch_object()) {
echo $row->product_name; // Product table
echo $row->image_src; // Image table
}
Problem: Only the first image of each product is printed, but I want to display all of them. All images are printed if I remove the "order by" part, but then the product_name is printed once for each image (so if one product has three images, the product_name would be printed three times as well).
How do I best solve this?
That's how GROUP BY works.
If you want to get all images for all products, you can solve that (at least) 3 ways:
1: Do not use GROUP BY, handle it in the loop, like:
$last_product = null;
while($row = $results->fetch_object()) {
if ($last_product !== $row->product_id) {
// new product starts here
$last_product = $row->product_id;
echo $row->product_name; // Product table
}
echo $row->image_src; // Image table
}
2: Use GROUP BY & query all images with different statements within the loop.
$products = <query products>;
while($row = $products->fetch_object()) {
echo $row->product_name; // Product table
$images = <query images for product in $row>;
while($row = $images->fetch_object()) {
echo $row->image_src; // Image table
}
}
3: Use aggregate string functions to get all images for a product. This is only works in special cases, f.ex. here, as URL cannot consist new lines, for example.
In MySQL:
select
{$tableProducts}.*,
group_concat({$tableImages}.image_src SEPARATOR '\n') as image_srcs
from {$tableProducts}
left join {$tableImages}
on {$tableImages}.product_id = {$tableProducts}.product_id
group by {$tableProducts}.product_id;
In PostgreSQL:
select
{$tableProducts}.*,
string_agg({$tableImages}.image_src, '\n') as image_srcs
from {$tableProducts}
left join {$tableImages}
on {$tableImages}.product_id = {$tableProducts}.product_id
group by {$tableProducts}.product_id;
In the loop:
while($row = $products->fetch_object()) {
echo $row->product_name; // Product table
foreach (explode("\n", $row->image_srcs) as $image_src) {
echo $image_src; // Image table
}
}

Grouping values from my_ MySQL to be shown in separate <div> on the basis of certain criteria

I am working on a php project with MySQL as database. Here is the table structure
product_id (PK)
shop_id (FK)
product_name
product_desc
Product_id is the primary key and shop_id is the foreign key (shows the product belongs to which shop). Now I want to select these product and display them in a <div>. For each shop products, I want to display a different <div>. e.g if there are three products say p1,p2 and p3, and they have same shop_id (say) 1, i want them to show in a separate <div>. there will be separate <div> for each shop_id, and all products belong to that shop_id will be displayed in that <div>. How can I do this with My_SQL query or using PHP. I have used a simple SELECT query like this but with this i could not find a way to initiate different <div> for separate shop.
$q = mysql_query("SELECT * FROM table");
echo "<div>";
while($product = mysql_fetch_assoc($q)){
echo $product['product_name']."<br/>";
}
echo "</div>";
It just throw all products in a single dive, I want separate div for separate shop (which contains all products of that shop). Thanks for reading..
Simplest way is to group the products by id in a array and loop through them
$all_products = array();
while($product = mysql_fetch_assoc($q)){
$all_products[$product['shop_id']][] = $product;
}
foreach($all_products as $shop_id => $product_array){
echo "<div id='shop_".$shop_id."'>";
foreach($product_array as $product){
echo $product['product_name']."<br/>";
}
echo "</div>";
}
OR call product data fro each shop id
$q = mysql_query("SELECT * FROM shops");
while($shops = mysql_fetch_assoc($q)){
$product_q = mysql_query("SELECT * FROM product_table WHERE shop_id=$shops['id']");
echo "<div>";
while($product = mysql_fetch_assoc($product_q)){
echo $product['product_name']."<br/>";
}
echo "</div>";
}

Categories