What's wrong with this INNER JOIN SQL query? - php

I have three tables, tblMembers, tblBooks and tblReviews. The idea is a book review website.
Currently the Book Title is only displayed if there are reviews written for it, however I want the book title to always be displayed along with; either a list of reviews, or, the text, 'this title has not yet been reviewed.'
What is wrong with this SQL query?
$sql = "
SELECT *
FROM tblBooks
INNER JOIN tblReviews
ON tblBooks.bookID = tblReviews.bookID
INNER JOIN tblMembers
ON tblReviews.userID = tblMembers.userID
WHERE tblReviews.bookID = :bookID";
$query = $odb->prepare($sql);
$query->execute(array(":bookID" => $bookID));
$results = $query->fetchAll();
echo "<h1>".$results[0]['longTitle']."</h1>";
if($results !== FALSE && $query->rowCount()>0) {
foreach($results as $result) {
echo "Reviewed by: " . $result['firstName'] . " " . $result['lastName'];
echo "<br />";
echo "Rating: " . $result['rating']."/100";
echo "<br />";
echo "Date: " . $result['reviewDate'] . " " . $result['reviewTime'];
echo "<br />";
echo "Review:";
echo "<br />";
echo $result['reviewText'];
echo "<hr />";
}
} else { // the book has not been reviewed yet
echo "There are no reviews for this title yet";
}
As mentioned above, the line echo "<h1>".$results[0]['longTitle']."</h1>"; is only executed if the book has reviews, I want to get the book details prior to checking if it has reviews or not. How can I do this?
On another note, how can I check which books haven't been reviewed yet and populate a drop down list with the results? - This has been answered :D
How can I either:
Populate two separate drop down lists, one for books that have reviews and one for books that haven't been reviewed yet (this one I can do as I have the SQL from the question above).
OR
Populate the single dropdown list but put books that have reviews at the top, separated by a string of characters, let's say "---------- THESE BOOKS HAVEN'T BEEN REVIEWED YET ----------" followed by the books that haven't yet been reviewed. Is this possible?

SELECT *
FROM tblBooks
LEFT JOIN tblReviews
ON tblBooks.bookID = tblReviews.bookID
LEFT JOIN tblMembers
ON tblReviews.userID = tblMembers.userID
WHERE tblReviews.bookID = :bookID
Will return all books regardless if there is a review or a member affiliated with it.
IF there is a review return it, and if the review has a member it as well. otherwise NULL values will come back in fields related to tblMembers or tblReviews.

Related

inner join gives back multiple values

I have products, All of these products have for example. An id, name and price. All of these products are connected in the database like this:
Since I don't have 10 reputation... Here is a link to a picture http://puu.sh/oS95c/b7b5b17427.png
What I want to achieve is to have products that are connected to another product show up on the screen using inner join. However instead of getting the connected items back I get back every item of the right column even if they are not connected.
Here is a link to get a better view of the database: http://puu.sh/oSBF2/1af1ce3751.png
$sql = "SELECT AFBEELDING_KLEIN, PRODUCTNAAM, PRIJS
FROM PRODUCT
inner JOIN PRODUCT_GERELATEERD_PRODUCT
ON PRODUCT.PRODUCTNUMMER=PRODUCT_GERELATEERD_PRODUCT.PRODUCTNUMMER_GERELATEERD_PRODUCT";
$result = sqlsrv_query($db, $sql);
$data = sqlsrv_fetch_array($result);
while($data = sqlsrv_fetch_array($result)) {
$big_picture = '<img src="../' . $data["AFBEELDING_KLEIN"] . '"' . 'alt="product">';
$link = '<a href="../productpaginas/' . $data["PRODUCTNAAM"] . '.php"<p> ' . $data["PRODUCTNAAM"] . '</p></a>';
$price = '<h2> €' . $data["PRIJS"] . '</h2>';
echo '<div class="product">';
echo $big_picture;
echo $link;
echo $price;
echo '</div>';
}
Since you immune to questions and don't provide more information, we can only guess.
You might want a m:n link back to the product table itself.
SELECT
p1.PRODUCTNUMMER, p2.AFBEELDING_KLEIN, p2.PRODUCTNAAM, p2.PRIJS
FROM
PRODUCT AS p1
INNER JOIN
PRODUCT_GERELATEERD_PRODUCT AS pgp
ON
p1.PRODUCTNUMMER = pgp.PRODUCTNUMMER
INNER JOIN
PRODUCT AS p2
ON
pgp.PRODUCTNUMMER_GERELATEERD_PRODUCT = p2.PRODUCTNUMMER
;

Display Multiple PHP Queries

I need to display multiple queries (they can't be combined into one large query, at least I don't think so) together in a webpage. I'll explain a little about the queries to give an idea of the problem. I have a database in MySQL with 3 question tables of the same format linked to a response table via a classid. The response table is linked to an instructor table via an instructorid. I need to display a table showing all 3 question scores for each record existing for an instructor, with each table followed by some text indicating which question had the highest value as well as the least. I created a uniontbl view in MySQL which is a union query with fields ClassID, Average and TableName. What I have so far is:
$query2 = "SELECT `tbl_instructor`.`FirstName`,
`tbl_instructor`.`LastName`,
`tbl_term`.`TermID`,
`tbl_ucourse`.`Abbreviation`,
`tbl_ucourse`.`Series`,
`tbl_uquestion01`.`Average` AS `Q1`,
`tbl_uquestion02`.`Average` AS `Q2`,
`tbl_uquestion03`.`Average` AS `Q3`
FROM `tbl_instructor`
LEFT JOIN `undergrad`.`tbl_uresponse` ON `tbl_instructor`.`InstructorID` = `tbl_uresponse`.`InstructorID`
LEFT JOIN `undergrad`.`tbl_ucourse` ON `tbl_uresponse`.`CourseID` = `tbl_ucourse`.`CourseID`
LEFT JOIN `undergrad`.`tbl_Term` ON `tbl_UResponse`.`TermID` = `tbl_Term`.`TermID`
LEFT JOIN `undergrad`.`tbl_uquestion01` ON `tbl_uresponse`.`ClassID` = `tbl_uquestion01`.`ClassID`
LEFT JOIN `undergrad`.`tbl_uquestion02` ON `tbl_uresponse`.`ClassID` = `tbl_uquestion02`.`ClassID`
LEFT JOIN `undergrad`.`tbl_uquestion03` ON `tbl_uresponse`.`ClassID` = `tbl_uquestion03`.`ClassID`
WHERE CONCAT(LastName, ', ', FirstName, ' (', UserID, ')') = '{$instructor}'";
$query3 = "SELECT `tbl_instructor`.`FirstName`,
`tbl_instructor`.`LastName`,
`uniontbl`.`ClassID`,
`uniontbl`.`TableName`,
`tbl_uresponse`.`InstructorID`
FROM `tbl_Instructor`
LEFT JOIN `undergrad`.`tbl_uresponse` ON `tbl_instructor`.`InstructorID` = `tbl_uresponse`.`InstructorID`
LEFT JOIN `undergrad`.`uniontbl` ON `tbl_uresponse`.`ClassID` = `uniontbl`.`ClassID`
WHERE CONCAT(LastName, ', ', FirstName, ' (', UserID, ')') = '{$instructor}'
ORDER BY `uniontbl`.`Average` DESC
LIMIT 1";
$query4 = "SELECT `tbl_instructor`.`FirstName`,
`tbl_instructor`.`LastName`,
`uniontbl`.`ClassID`,
`uniontbl`.`TableName`,
`tbl_uresponse`.`InstructorID`
FROM `tbl_Instructor`
LEFT JOIN `undergrad`.`tbl_uresponse` ON `tbl_instructor`.`InstructorID` = `tbl_uresponse`.`InstructorID`
LEFT JOIN `undergrad`.`uniontbl` ON `tbl_uresponse`.`ClassID` = `uniontbl`.`ClassID`
WHERE CONCAT(LastName, ', ', FirstName, ' (', UserID, ')') = '{$instructor}'
ORDER BY `uniontbl`.`Average` ASC
LIMIT 1";
$result2 = mysqli_query($query2);
$result3 = mysqli_query($query3);
$result4 = mysqli_query($query4);
while($row2 = mysqli_fetch_assoc($result2))
{
echo "<br>";
echo"<table>";
echo "<tr>";
echo "<th>Q1</th>";
echo "<th>Q2</th>";
echo "<th>Q3</th>";
echo "</tr>";
echo "<tr>";
echo "<td>" . $row2['Q1'] . "</td>";
echo "<td>" . $row2['Q2'] . "</td>";
echo "<td>" . $row2['Q3'] . "</td>";
echo "</tr>";
echo"<br>";
echo "</table>";
while($row3 = mysqli_fetch_assoc($result3))
{
echo $row3['TableName'];
}
echo "<br>";
while($row4 = mysqli_fetch_assoc($result4))
{
echo $row4['TableName'];
}
echo "<br>";
}
So, how I've tried to tackle the problem is using the second and third queries to determine which questions had the highest and lowest score from the uniontbl view and displaying that after each table containing the question scores. The problem is that the second and third queries ONLY display after the first table (or record) and do not show at all after that. I have a feeling that the problem lies in the actual queries themselves but I can't think of another way to solve the problem. P.S. I know my code isn't the best (echoing HTML and such) but I'm just trying to get it to work...
After you print the first row of $result2, you fetch all the rows of $result3 and $result4. So after you print the second row of $result2, there's nothing left to fetch from the second and third queries.
Since the second and third queries use LIMIT 1, there's just one row for each of them. You could fetch them each once, and then display that row after each row of the first query. But I'm not sure why you need to display the same thing multiple times. Maybe you should just show the output of these two queries once, at the beginning or end, rather than after each row.
Also, do you really want to create a whole new table for each row of $result2? Usually each row is just a row in one big table, not a separate table with just one row for each row from the DB.

Trying to use variable in MySQL INNER JOIN

I am a php and MySQL newbie. What I have done is created an html form with a <select> dropdown. Based on the selection from the form, it changes the $_SESSION[campaignID] variable. Changing the selection in the form is supposed to then change what displays on the page. The page consists of a forum style post that allows users to fill out a textarea and then submit it into the MySQL database into a table called "posts." On this same page I then display the contents of the "posts" table.
What I have done is in the posts MySQL table, I have added a campaignID row. Then in my campaigns table I also have a campaignID row. The campaignID in campaigns table auto increments every time a campaign is created. Then with the earlier mentioned dropdown I can select the campaign I want, and it should then show all posts with the same campaignID as the campaign I selected.
I can verify that the $_SESSION[campaignID] is changing when i select the various options. Because when I do that and then save another post, it takes the session variable campaignID and saves it properly in the posts table.
Now what I need it to do, is when I change the drop down (which then changes $_SESSION[campaignID]) I need it to display the posts that share the same campaignID as the selected campaign. I am just not able to get it to display when trying to put a variable in my INNER JOIN query. I have a feeling the info I have provided may not be enough, but not sure what else I need to include here. Help?
Code that contains the INNER JOIN query and displays the various rows of posts table
UPDATED
<?php
$con=mysqli_connect("localhost","dorians","ds2953!b67P$","aldentec");
// Check connection
if (mysqli_connect_errno())
{
echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
$campaignID = $_SESSION['campaignID'];
$result = mysqli_query($con,"SELECT posts.postDate, posts.postName, posts.postEntry FROM posts INNER JOIN campaigns ON posts.campaignID=" . $campaignID);
while($row = mysqli_fetch_array($result))
{
echo "<div id='campaignPostContainer'>";
echo "<ul class='campaignPostBox'>";
echo "<p class='postInfo'>";
echo "Posted on:";
echo "<li>" . $row['postDate'] . "</li>";
echo "</p>";
echo "<p class='postInfo'>";
echo "Posted by:";
echo "<li>" . $row['postName'] . "</li>";
echo "</p>";
echo "<li class='postEntry'>" . $row['postEntry'] . "</li>";
echo "</ul>";
echo "</div>";
echo "<hr>";
}
mysqli_close($con);
?>
Without going into a use-prepared-statements rant...
You're not pulling the session variable, but assigning $campaignId to literally the string $_SESSION[campaignID].
Change your line:
$campaignID = '$_SESSION[campaignID]';
to:
$campaignID = $_SESSION['campaignID'];
Also, your query is going to generate a cross product unless you define something in your ON clause like:
SELECT posts.postDate, posts.postName, posts.postEntry FROM posts
INNER JOIN campaigns ON posts.campaignID= $campaignID
AND posts.campaignID= campaigns.id
The value should be in single quote ' so you may try this
posts.campaignID='" . $campaignID ."'"
instead of
posts.campaignID=" . $campaignID

While loop displaying result 3 times

Basicly I'm trying to make a simple news feed but I'm stuck at the moment as my while loop display the result 3 times, why is this? :/
<?php
$sql ="SELECT
*
FROM
news,
admins";
$result = mysql_query($sql);
if(!$result)
{
echo 'Error while selecting from database. Please contact the administration team';
} else {
while($row = mysql_fetch_assoc($result))
{
echo '
<div class="content_news">
<h1>' . $row['news_name'] . '</h1>
<p style="font-size:12px;">Posted by <b>' . $row['admin_name'] . '</b> on ' . $row['news_date'] . '
<p>' . $row['news_description'] . '</p>
read more
</div>
';
}
}
?>
If you'd like to see what I am talking about: http://freewallpaperblog.com/freshrp/
Ignore the last 2(those are static html not php)
your query selects data from 2 tables (news, admins) so it joins every row of 1st table with every row of 2nd table
SELECT * FROM news, admins
i recommend you to use following query
SELECT news.*, admins.admin_name FROM news
INNER JOIN admins ON news.admin_id = admins.id
where admin_id is your correct column name
You either have 3 admins or 3 rows of news. Your query makes a direct multiplication between tables. Try "left join" instead...
SELECT * FROM news
INNER JOIN admins ON admins.id = news.adminid
Or whatever adminid is in the news table.
Try the following query:
SELECT
*
FROM
news
Inner join admins on news.admin_id = admins.id
You made no JOIN statement in your SQL, as someone else has already commented on in your question. It would help if you posted the associated fields you're grabbing, but based on your $row keys, my best guess is the following should work for you (but I can't promise it will without knowing how your database is designed, I can only infer from the variable names):
$sql = "SELECT news.name, news.date, news.description, news.link, admins.name"
. "FROM news"
. "INNER JOIN admins"
. "ON news.name=admins.name"
References:
http://www.w3schools.com/sql/sql_join_inner.asp
http://www.w3schools.com/sql/sql_join_left.asp
http://dev.mysql.com/doc/refman/5.0/en/join.html

Doing an SQL query in PHP where a field from a different table is referenced

OK,
In this query I am displaying the sales for a particular person, matching the passport number from the current form I am working on.
What I want to do however, is to sum the total sales and display it, excluding records which have been marked as paid.
I am having trouble because "paid" does not existent in the current form I am working on as a variable, nor the table it relates to.
I can´t use row['paid'] as I need to do this query outside of the while loop.
What should I do in this situation?
$sqlstr = mysql_query(
"SELECT * FROM sales where passport = ".
"'{$therecord['passport']}'");
if (mysql_numrows($sqlstr) != 0) {
echo "<b>Sales for {$therecord['firstname']} ".
"{$therecord['lastname']}</b><br />";
echo "<table><tr>";
echo '<tr><th align="left">Name</th><th align="left">Quantity</th>".
"<th align="left">Cost</th></tr>';
while ($row = mysql_fetch_array($sqlstr)) {
echo "<td>{$row['product']}</td>";
echo "<td>{$row['quantity']}</td>";
echo "<td>{$row['cost']}</td>";
echo "</tr>";
}
}
echo "</table>";
$sqltotal = mysql_query(
"SELECT SUM(cost) as total FROM sales where passport = ".
"'{$therecord['passport']} AND {$therecord['paid']} <> 1'");
$row = mysql_fetch_array($sqltotal);
echo "<br /><b>Total Owing: {$row['total']}</b>";
You could either create a MySQL view, of look at SQL joins. I'm not sure on your database structure, but you should have a SQL query like this:
SELECT SUM(sales.cost) AS total
FROM sales, table2
WHERE sales.passport = '$passport_id'
AND sales.passport = table2.passport
AND table2.paid = '1'
Not sure as that was wrote off-hand. Again, it'd be better if we knew the structure of your tables.
you've misplaced simple quote in :
"'{$therecord['passport']} AND {$therecord['paid']} <> 1'"
it must be :
"'{$therecord['passport']}' AND {$therecord['paid']} <> 1"

Categories