PHP: MYSQL COUNT query with linked tables - php

I am looking for a cleaner way to do this. My code works, but I know it can be better. I have three tables: one with a list of Category Groups, One with a list of categories that are linked to category groups, and one with a list of news stories that are linked to the categories.
I need to loop through all of the names of the Category Groups, followed by the names of the categories that are in the category groups, with the number of news stories in each category listed as well.
I have three tables: CategoryGroups, Categories, News.
I have a set of queries. The first queries all the rows from the CategoryGroups table:
$result = mysql_query( '
SELECT cat_group_id, cat_group_name FROM CategoryGroups
' );
The second query is inside the looped results of the first query and finds all the categories that have a news item and are linked to a specific category group:
<?php
while( $row = mysql_fetch_assoc( $result ) ){
$id = $row['cat_group_id'];
$name = $row['cat_group_name'];
echo "<h3>$name</h3>";
$sql = mysql_query("
SELECT category_id, title FROM `Categories`
WHERE cat_group_id = $id
AND category_id IN
(SELECT news.category_id FROM news)
");
while( $row = mysql_fetch_assoc($sql) ) {
$title = $row['title'];
$catid = $row['category_id'];
$numbers = mysql_query("
SELECT * FROM news
WHERE category_id =$catid"
);
$nums = mysql_num_rows($numbers);
echo "$title ($nums)<br/>\n";
}
?>
I would like to limit this to one or two queries, with efficiency in mind. I know this can be done, however I have not been successful in my attempts.
thanks.

Why not JOIN the tables?
SELECT cat_group_name, title, count(newsid)
FROM CatagoryGroups
INNER JOIN Categories ON cat_group_id
INNER JOIN News ON category_id
GROUP BY cat_group_name, title
looks like it should be close, if table news has a newsid column (it's gotta have SOME primary key, right? well, count that;-). With the obvious indexes the JOINs should be quite fast, and your PHP code can do whatever output formatting you may need from that.

I suggest you need to get a book on SQL, such as "SQL Queries for Mere Mortals."
$sql = mysql_query("
SELECT cg.cat_group_name, c.title, COUNT(n.category_id) AS NumNews
FROM `CategoryGroups` cg
JOIN `Categories` c USING (cat_group_id)
JOIN `News` n USING (category_id)
GROUP BY cg.cat_group_name, c.title");
Then loop over the result and output a new <h3> each time the cat_group_name is different from the previous row.

Related

From two tables from my database i would like to echo a column with click counts

In my database i have created two tables , the one is "categories" and the other "click_count".
The two tables have the following information : categories( cat_id, cat_name , cat_description ) and click_count(id, cat_id, cat_count). I have already written a php code which echo a table with information about categories and i have already written a php code whick calculates the click counts, so i want a php script which i can echo on the same table the information about click_count and specify the "cat_count" which contains the number about "clicks" . The following code is obviously wrong but you can get the logic.
<?php
$sql4 = "SELECT categories.cat_id,categories.cat_name,click_count.cat_id,click_count.cat_count WHERE categories.cat_id=click_count.cat_id";
$result4 = mysqli_query($conn, $sql4);
$row4 = mysqli_fetch_array($result4);
while($row4 = mysqli_fetch_assoc($result4)) {
echo '<td>'.$row4['cat_count']; }?>
The SELECT statement should contain a JOIN:
SELECT categories.cat_id, categories.cat_name, click_count.cat_id, click_count.cat_count
FROM categories
LEFT JOIN click_count
ON categories.cat_id = click_count.cat_id;
...and you can also add a WHERE clause at the end if you need it to select not all, but only the ones that fit a certain condition.

How to only display a category once from SQL table?

I have a table of products with a column (prodCat) which is an ID column number, this relates to another table I have set-up (rangecat) which links to a column (rangeCatID).
My code is as follows:
<?php
$querycat = "SELECT DISTINCT products.prodCat, rangecat.rangeCatTitle, rangecat.rangeCatSEO FROM products INNER JOIN ranges ON products.prodRangeID = ranges.rangeID INNER JOIN rangecat ON products.prodCat = rangecat.rangeCatID WHERE rangeSEO = '$seoname' AND prodState = 1";
$resultcat = $conn->query($querycat);
while($rowcat = $resultcat->fetch_object()){
if ($page[3] == $rowcat->rangeCatSEO) { $state = ' class="onstate"'; } else { $state = ''; }
echo '<li ' .$state. '>' . $rowcat->rangeCatTitle . '</li>';
}
$resultcat->free();
?>
Please see following screenshot below which show the category returned multiple times:
Please see below for products table structure:
Please see below for rangecat table structure:
Given that your query has related tables, then the "duplicates" come from the fact that there are related rows in the categories table with other rows in the other tables.
If you want to get only unique rows, you must use either select distinct or group by. I'd go with select distinct:
SELECT DISTINCT category -- Or the appropriate column name
FROM products
INNER JOIN ranges ON products.prodRangeID = ranges.rangeID
INNER JOIN rangecat ON products.prodCat = rangecat.rangeCatID
-- Add where conditions here
Once you've got the unique category, you can create a second statement to get the products for each unique category.
Hope this helps

Join ID & Name from Two Separate Tables

I have two tables...
Table 1 (keywordsTbl)
KeyID Key_Name
================================
1 Biology
2 Entertainment
Table 2 (profileTbl)
Keyword_ID Key_Name
================================
1(from keywordsTbl) Biology(from keywordsTbl)
2(from keywordsTbl) Entertainment(from keywordsTbl)
My query in profileTbl is indexing KeyID from the keywordsTbl and its working fine. The only problem is my output shows up like so (no array). :
Seems like its indexing only the 1st keyID... The results only show 1 single keyword even though there are more than one keyID being placed in the row:
My query looks as so:
include 'db.php';
$sql = mysqli_query($con,"SELECT * FROM profileTable, addKeywordTable ORDER BY LaName ASC");
while ($row = mysqli_fetch_array($sql))
{
$fname = $row['FirName'];
$lname = $row['LaName'];
$title = $row['Title'];
$keys = $row['Keyword_Name'];
$id = $row['source_ID'];
if(!in_array($title,array('',null)) && !empty($title)):
$title = '('.$title.')';
else:
$title = '';
endif;
What's the easiest way to show an array when two tables are being used? Would a join work better in this case?
I am not 100% sure that this is what you are asking, but if you want a list of results based on a join for KeyID you can do something like this:
SELECT p.Laname, p.FiName, GROUP_CONCAT(k.Key_Name)
FROM ProfileTable AS p
JOIN addKeywordTable AS k ON k.KeyID = p.Keyword_ID
GROUP BY p.LaName, p.FiName
If you want to include more files in the select list you need to add them to the GROUP BY list or use an aggregate function (GROUP_CONCAT, MAX, MIN, etc) on them in the select list.

mysql: group results, limit them and join to other tables in one query

i have a online application for wich i require a sort of dashboard (to use the white-space).
There are three tables used for the operation:
1.) categories: id, name
2.) entries: id, name, description, category_id, created, modified
3.) entryimages: id, filename, description, entry_id
on the dashboard i want to show 4-5 entries (with thumbnail images, so i require joins to the entryimages table and the categories table) for each category.
I read through some articles (and threads on s.o.) like this one:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
But am still not getting it right, i've tried to first extract all categories and for each and every category build a query and with "all union" attach them to one, but that is not working.
The last version of code i used:
foreach($categories as $id => $name)
{
$query .= "SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry` LEFT JOIN `entryimages` ON `entryimages`.`entry_id` = `entry`.`id`
WHERE `entry`.`category_id` = $id ";
if($i < count($groups))
{
$query .= 'UNION ALL ';
}
$i++;
}
$result = mysql_query($query);
Does anybody know what is the best right to accomplish this operation?
Thanks 1000
On the dashboard if you want to show three entries, the way you are doing is wrong. If my understanding is right, the entire query will be something like
"SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry`
INNER JOIN categories
ON (entry.category_id = categories.id)
LEFT JOIN (SELECT * FROM `entryimages` WHERE `entry_id` = `entry`.`id` LIMIT 1) AS `entryimages`
ON `entryimages`.`entry_id` =`entry`.`id`
ORDER BY `entry`.`created` DESC LIMIT 5";
Your code looks ok to me you should just add a LIMIT clause so that you get just five of them and an ORDER BY clause to get the latest
$query .= "SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry` LEFT JOIN `entryimages` ON `entryimages`.`entry_id` = `entry`.`id`
WHERE `entry`.`category_id` = $id ORDER BY `entry`.`created` DESC LIMIT 5";

Select from one table, and count from another table in same query

I have quite a bit of knowledge about SQL queries.
I'm trying to make gallery, and I need to select categories from table "cat_photos", which contain rows (id,name,cover,photo) and count number of photos from table "photos" which contain rows (id,thumb,photo,category).
Here is code which i use:
1) Selecting categories
$query = mysql_query("SELECT * FROM cat_photos ORDER BY ID DESC");
while($data = mysql_fetch_array($query)) {
echo "<li><a href='photos.php?cat=$data[id]'><img src='galleries/categories/$row[image]' alt='$row[name]' /></a>
<div class='photodesc'><div class='catname'><a href='photos.php?cat=$row[id]'>$row[name]</a></div>
<div class='catcount'>Number of photos in category</div></div></li>"; }
2) Counting number of photos in category
$query = mysql_query("SELECT category, COUNT(photo) FROM photos GROUP BY category") or die(mysql_error());
while($row = mysql_fetch_array($query)){
echo "Number of photos is ". $row['COUNT(photo)'] ." in cateogry ". $row['category'] .".";
echo "<br />"; }
Separated all works, but I can't find a way to merge them into one query.
I have googleing for "UNION", "JOIN", "LEFT JOIN" options in MySql query but I could't together the pieces.
I wonder if this is in general possible?
How in order that query look like?
Try this, it should work :
SELECT cat_photos.*, count(photos.id) as number_photos
FROM cat_photos
LEFT JOIN photos ON photos.category = cat_photos.id
GROUP BY cat_photos.id, cat_photos.name, cat_photos.image
ORDER BY cat_photos.id
The number of photos will be accessible trough $row['number_photos'].
Just use your second query and join the wanted category elements.
Something quick and dirty would be:
SELECT c.category, COALESCE(COUNT(p.photo),0) as photos FROM photos p, cat_photos c
WHERE c.category = p.category
GROUP BY category
Since I don't know your exact database setup just change the selected elements to the ones you really need.
//edit: Put in Coalesce to get categories with 0 photos.
Don't SELECT *. Instead select individual columns and then join:
SELECT
cat_photos_main.id, cat_photos_main.category, cat_photos_main.photodesc, cat_photos_counts.num_photos
FROM cat_photos cat_photos_main
LEFT OUTER JOIN (SELECT category, count(*) AS num_photos FROM photos GROUP BY category) cat_photos_counts
ON cat_photos_main.category = cat_photos_counts.category

Categories