Excluding a variable when its value is blank - php

The code below works great. I have a MySQL database that contains book titles classified in different categories. In the code below, the variable "site" represents a book title. Each category is represented by a different table in the MySQL database.
The code below ranks the top 25 book titles (site) by total votes across all categories (MySQL tables). I am trying to exclude blank book titles (i. e. when site = ''). How can I do this?
I have tried inserting WHERE site != '' in a few places but I get an error message. So I guess I'm asking, where can I insert WHERE site != ''?
Thanks in advance,
John
<?
mysql_connect("mysqlv10", "username", "password") or die(mysql_error());
mysql_select_db("database") or die(mysql_error());
$result = mysql_query("SHOW TABLES");
$tables = array();
while ($row = mysql_fetch_assoc($result)) {
$tables[] = '`'.$row["Tables_in_bookfeather"].'`';
}
$subQuery = "SELECT site, votes_up FROM ".implode(" UNION ALL SELECT site, votes_up FROM ",$tables);
// Create one query that gets the data you need
$sqlStr = "SELECT site, sum(votes_up) sumVotesUp
FROM (
".$subQuery." ) subQuery
GROUP BY site ORDER BY sum(votes_up) DESC LIMIT 25";
$result = mysql_query($sqlStr);
$arr = array();
echo "<table class=\"samples2\">";
while ($row = mysql_fetch_assoc($result)) {
echo '<tr>';
echo '<td class="sitename2">'.$row["site"].'</td>';
echo '<td>'.$row["sumVotesUp"].'</td>';
echo '</tr>';
}
echo "</table>";
?>

You shouldn't have separate tables for each book category. I can't believe you have so many books that any of these tables would grow too large. Any scalability benefits you might gain by splitting the table are offset by the complexity of having to do these UNION queries.
Here's what I'd do:
Unify the tables into one table.
Add a Categories table.
Relate books to categories with a many-to-many table.
Then your SQL query becomes much simpler:
$sqlStr = "SELECT site, votes_up FROM Books
WHERE site IS NOT NULL AND site <> ''
ORDER BY votes_up DESC LIMIT 25";

It's probably safest to put it in the subquery:
$subQueryParts = array();
foreach($tables as $table)
$subQueryParts[] = "SELECT site, votes_up FROM $table WHERE LENGTH(site)";
$subQuery = implode(" UNION ALL ", $subQueryParts);
If possible, you should follow Bill Karwin's advice and store all your books in one table. Dynamic table names are very hard to search and manage, and they do not optimize well.

Related

php loop start over when num_rows==0

I'm trying to write a php code to select form tables:
books
images
Some books does not have an image, so I want to skip it and select another book.
I have wrote this code but it does not work with me perfectly.
Now I'm getting only 5 records! it must be 6 as I limited in the book select query.
$slider_sql = "select * from books limit 6";
$slider_result = $conn->query($slider_sql);
while($slider_row = $slider_result->fetch_assoc()) {
extract($slider_row);
$img_sql = "SELECT big_img FROM images WHERE book_id = '$id'";
$img_rs = $conn->query($img_sql);
$img_row = $img_rs->fetch_assoc();
if ($img_rs->num_rows == 0)
continue; //--> here I want to start while again to select another book.
echo $book_name.'<br>';
echo $img_row['big_img'].'<br>';
}
Thanks for your help and time!
Instead of having a sub-query in a loop (which is nearly ALWAYS a bad idea!), use a JOIN instead, which simplifies it to one query instead of two. Then set a condition that big_img should not be empty. This guarantees that you will only find rows where there's an image matching the book. LIMIT will still only ensure the return of 6 rows. <> in MySQL is the same as !=.
$slider_sql = "SELECT b.book_name, i.big_img
FROM books b
JOIN images i
ON i.book_id=b.id
WHERE i.big_img <> ''
LIMIT 6";
$result = $conn->query($slider_sql);
while ($row = $result->fetch_assoc()) {
echo $row['book_name'].'<br>';
echo $row['big_img'].'<br>';
}
MySQL JOIN

PHP, SQL - getting fetch where table id = user id and count other table where row is = user id

Thanks for helping, first I will show code:
$dotaz = "Select * from customers JOIN contracts where customers.user_id ='".$_SESSION['user_id']."' and contracts.customer_contract = ".$_SESSION['user_id']." order by COUNT(contracts.customer_contract) DESC limit $limit, $pocetZaznamu ";
I need to get the lists of users (customers table) ordered by count of contracts(contracts table)
I tried to solve this by searching over there, but I can't... if you help me please and explain how it works, thank you! :) $pocetZanamu is Number of records.
I need get users (name, surname etc...) from table customers, ordered by number of contracts in contracts table, where is contract_id, customer_contract (user id)..
This should do it where is the column name you are counting.
$id = $_SESSION['user_id'] ;
$dotaz = "Select COUNT(`customer_contract`) AS CNT, `customer_contract` FROM `contracts` WHERE `user_id`=$id GROUP BY `customer_contract` ORDER BY `CNT` DESC";
Depending on what you are doing you may want to store the results in an array, then process each element in the array separately.
while ($row = mysqli_fetch_array($results, MYSQL_NUM)){
$contracts[$row[1]] = $row[0];
}
foreach ($contracts AS $customer_contract => $count){
Process each user id code here
}
Not sure what you are counting. The above counts the customer_contract for a table with multiple records containing the same value in the customer_contract column.
If you just want the total number of records with the same user_id then you'd use:
$dotaz = "Select 1 FROM `contracts` WHERE `user_id`=$id";
$results = $mysqli->query($dotaz);
$count = mysql_num_rows($results);

How performance is affected by storing categories as comma delimited array and extracting each in a loop?

Namastey!
I'm currently working on one of my projects where I get to one doubt.
What I'm doing is:
I have got 4 tables called:
1: project_degree
2: project_department
3: project_category
4: Projects
project_degree have got four top level degrees which are: B.tech, M.tech, M.C.A. & M.B.A.
project_department have got their respective departments such as: C.S.E, I.T., E.E.E. and so on.
Now, project_category have some categories like PHP, .NET, SAP etc.
What I'm trying to do is, I'm adding a project to database called "projects" where I'm assigning it to its degree, department and category.
Structure of projects table is as follows:
id | project name | degree_id | Dept_id | Cat_id
1 | Sample project | 1 | 3 | 4,3,6,5,9
Now as you can see above, field "cat_id" have got multiple categories where each categories ID have been separated by a comma.
Now when I call a query get all projects from the table called "projects", I want to list of categories related to that particular project and my code goes like this:
$query = mysql_query("SELECT * from projects ORDER BY id DESC");
while($row = mysql_fetch_array($query)) {
$categories = $row['cat_id'];
$cat_arr = explode(',',$categories);
$cat_size = sizeof($cat_arr);
for($i=0;$i<$cat_size;$i++) {
$get_cat = mysql_query("SELECT * from project_category WHERE id='".$cat_arr['$i']."'");
$cat_row = mysql_fetch_array($get_cat);
echo $cat_row['name']; // Here finally I'm getting categories name
}
}
So, finally I'm running nested loop and two queries to get a category name. I doubt it affect the page load time when it comes to huge data.
Is there any better alternative to this situation?
Here should be work
$query = mysql_query("SELECT * from projects ORDER BY id DESC");
while($row = mysql_fetch_array($query)) {
$get_cat = mysql_query("SELECT * from project_category WHERE id IN (" . $row['cat_id'] . ")");
$cat_row = mysql_fetch_array($get_cat);
echo $cat_row['name']; // Here finally I'm getting categories name
}
But normalization is better.
It's better to add a new table, project_has_catID where you can store project.id and cat.id as two columns (project_id and cat_id). Remove the Cat_id column in the project table.
Once done, simply select the name by the next query;
$query = mysql_query("SELECT project_category.name from project_category INNER JOIN project_has_catID phc ON phc.cat_id = project_category.id ORDER BY phc.project_id DESC");
By this, you have a list of category names. You don't have to loop with multiple database communications.
You could load all category names into an associative array first, then look up category names in this array when looping through the projects.
$categoryNames = array();
$query = mysql_query("SELECT id, name FROM project_category");
while ($row = mysql_fetch_array($query))
{
$categoryNames[$row['id']] = $row['name'];
}
$query = mysql_query("SELECT * FROM projects ORDER BY id DESC");
while ($row = mysql_fetch_array($query))
{
$categoryIds = explode(',', $row['cat_id']);
foreach ($categoryIds as $cat_id)
{
$cat_name = $categoryNames[$cat_id];
//do what you want with the name here
}
}
This way, you don't have to change your database structure, or the structure of your code. And you only have to execute two queries in total, so this is by far the simplest solution.
Needless to say, normalization is always better as others have indicated (never use a column that contains multiple comma-separated values), but you probably knew that and had your reasons for setting up your database tables this way.

MySQL select from multiple identical tables and display results randomly with php

Hello I would like to query multiple identical tables in my db which has different prefixes and than display the results randomly but somehow I need to track the origin of the item and I couldn't figure out how
I do the query like this because I don't have access to information_schema
$query = "SHOW TABLES FROM mydb WHERE RIGHT( tables_in_mydb, 5 ) = 'table'";
$res = mysql_query($query);
$num = mysql_num_rows($res);
while($row = mysql_fetch_row($res)) {
$numbers = explode('_', $row[0]);
if($num > 0) {
$q = "SELECT `this`, `that`, `something` FROM ".$numbers[0]."_idetinticaltables"; // :)
$r = mysql_query($q);
while($c = mysql_fetch_array($r)) {
/*display the results randomly with an identifier where the come from*/
}
}
}
You could use ORDER BY RAND() to randomly sort it
The following might work:
Get the list of the tables you're interested in. You already do that.
Create a UNION of multiple SELECT statements. Each SELECT statement differs for the table being selected from and you add a column set to the name of the table (so you can identify it later):
(SELECT *, TABLENAME = 'first_name_of_table' FROM first_name_of_table ...)
UNION
(SELECT *, TABLENAME = 'second_name_of_table' FROM second_name_of_table ...)
UNION
...
ORDER BY RAND() LIMIT 10;
Because it is a UNION you can randomize the whole order then. See How can i optimize MySQL's ORDER BY RAND() function? because it is not that trivial to do well, the example above is only to have an ORDER BY and LIMIT clause placed there. With many entries in your tables, it will kill your server.
$aa=array()
while($c = mysql_fetch_array($r))
{
/*display the results randomly with an identifier where the come from*/
$aa[]=$c;
}
echo $aa; // print "Array"

Getting data from 2 related and 1 unrelated MySQL tables with one query?

I am trying to create an archives page for my blog, which is also still being built. I have three different MySQL tables I need to pull data from and 1 of them is unrelated from the other 2. I found a similar post here but seeing as how I am not very experienced with PHP I am not able to figure out how to convert that to what I need. I know this can easily be done by executing three different queries, but that will put an unnecessary load on the server and slow down page load times and everything else.
The 2 related categories are "blogs" and "categories" while the third is for a different application built into the blog called the "Brain Link"
Here are the two queries for the related tables:
$blogQuery = mysqli_query($link, "SELECT * FROM pub_blogs ORDER BY id DESC") or die ("Could not access DB: " . mysqli_error($link));
$row = mysqli_fetch_assoc($blogQuery);
$blogID = $link->real_escape_string($row['id']);
$title = $link->real_escape_string($row['title']);
$date = $link->real_escape_string($row['date']);
$category = $link->real_escape_string($row['category']);
$content = $link->real_escape_string($row['content']);
$blogID = stripslashes($blogID);
$title = stripslashes($title);
$date = stripslashes($date);
$category = stripslashes($category);
$content = stripslashes($content);
$catQuery = mysqli_query($link, "SELECT * FROM categories ORDER BY id DESC") or die ("Could not access DB: " . mysqli_error($link));
$row = mysqli_fetch_assoc($catQuery);
$catID = $link->real_escape_string($row['id']);
$catName = $link->real_escape_string($row['name']);
$description = $link->real_escape_string($row['descriptions']);
$catID = stripslashes($catID);
$catName = stripslashes($catName);
$description = stripslashes($description);
and here is the third unrelated query:
$brainQuery = mysqli_query($link, "SELECT * FROM brain_links ORDER BY id DESC") or die ("Could not access DB: " . mysqli_error($link));
$row = mysqli_fetch_assoc($brainQuery);
$brainID = $link->real_escape_string($row['id']);
$site_name = $link->real_escape_string($row['site_name']);
$site_url = $link->real_escape_string($row['site_url']);
$post_date = $link->real_escape_string($row['post_date']);
Is it possible to get data from all three of these with one query? If not can someone point me in the direction of somewhere that will tell me how to join the two related ones?
The blog table saves the category ID under the 'category' column to identify which category it belongs to
I appreciate any help or suggestions!
This will bring the data from two tables. How ever, from the third tables data can't be get
SELECT
*
FROM pub_blogs
LEFT JOIN categories on categories.id = pub_blogs .category
ORDER BY id DESC
Ajnd for the third table you can not get it because you can not make a link to any other table. If you change your table structure you can do it.
No you cant get data from 3 rd table using same query .
Mysql wants a mapping between two tables .
You can join the blog and category but not the brain links
For the first two tables do :
select * , c.id , c.name , c.descriptions from pub_blogs p join categories c on c.id = p.category order by id desc ;
For the third table as there is no mapping you cant join it .
Happy Coding :)

Categories