tags:

views:

65

answers:

3

Hello,

The code below works great. It combines data from two MySQL tables. I would like to modify it by pulling in some data from a third MySQL table called "comment."

In the HTML table below, "title" is a field in the MySQL table "submission." Every "title" has a corresponding "submissionid" field. The field "submissionid" is also found in the "comment" MySQL table.

In the HTML table below, I would like "countComments" to equal the number of times a field called "commentid" appears in the MySQL table "comment" for any given "submissionid," where the "submissionid" is the same in both the "submission" and "comment" tables, and where the "submissionid" corresponds to the "title" being used.

Here's the catch: if there is no row in the MySQL table "comment" that corresponds with the "submissionid" being used for "table", I would like "countComments" to equal to zero.

How can I do this?

Thanks in advance,

John

$sqlStr = "SELECT s.loginid, s.title, s.url, s.displayurl, l.username
             FROM submission AS s,
                  login AS l
            WHERE s.loginid = l.loginid
         ORDER BY s.datesubmitted DESC
            LIMIT 10";


$result = mysql_query($sqlStr);

$arr = array(); 
echo "<table class=\"samplesrec\">";
while ($row = mysql_fetch_array($result)) { 
    echo '<tr>';
    echo '<td class="sitename1"><a href="http://www.'.$row["url"].'"&gt;'.$row["title"].'&lt;/a&gt;&lt;/td&gt;';
    echo '</tr>';
    echo '<tr>';
    echo '<td class="sitename2"><a href="http://www...com/sandbox/members/index.php?profile='.$row["username"].'"&gt;'.$row["username"].'&lt;/a&gt;&lt;a href="http://www...com/sandbox/comments/index.php?submission='.$row["title"].'"&gt;'.$row["countComments"].'&lt;/a&gt;&lt;/td&gt;';
    echo '</tr>';
    }
echo "</table>";
A: 

If I understand your issue correctly, how about:

SELECT s.loginid, s.title, s.url, s.displayurl, l.username, COUNT(c.id) AS commentCount
FROM submission AS s
LEFT JOIN login AS l ON l.loginid = s.loginid
LEFT JOIN comments AS c ON c.submissionid = s.id
ORDER BY s.datesubmitted DESC
LIMIT 10
webbiedave
Hmm... I tried it but it's coming up blank. As if the query has no results.
John
You have to modify it to ensure the fields are correct. For instance, I wrote COUNT(c.id) but I have no idea what your comments table's primary key is called. Just make sure all the field/table names are correct before running it.Also, make sure you are reading the errors from the database for additional clues.
webbiedave
Thanks... I did make sure that the fields are correct.
John
+1  A: 

You are doing an INNER JOIN, but you need an OUTER JOIN, in particular, a LEFT JOIN. With a LEFT JOIN, the table "on the left" is always joined, and if there is no correspondence the fields of the table on the right are set to null. The difference is explained very well in this wikipedia page.

Then you have to group the rows with the same submission id and count how much rows have been grouped, taking care that if one submission has only one comment and another have none they both have 1 grouped row... If one submission has no comments, in the next query c.submissionid will be null, so

Your SQL could be

SELECT s.loginid, s.title, s.url, s.displayurl, l.username, c.submissionid, 
IF(c.submissionid IS NULL, 0, COUNT(*))  AS countComments
FROM submission AS s
INNER JOIN login AS l ON l.loginid = s.loginid
LEFT JOIN comments AS c ON c.submissionid = s.id
GROUP BY (s.id)
ORDER BY s.datesubmitted DESC
LIMIT 10

There can be errors, I have not tested the query... But I hope to have given you the right idea, that is the difference between outer joins and inner joins.

Nicolò Martini
Two things - once you use group by you have to either include remaining fields under group by or use aggregate functions on them (max, min, avg, sum, count, etc...)At the same time if select is properly written it would not need IF. See here http://stackoverflow.com/questions/2496066/using-a-join-with-three-tables-when-a-field-might-be-null/2496406#2496406
Unreason
I've done a test and all works as expected... If s.id is unique for each submission (for example it is a primary index) you don't need to group by other fields
Nicolò Martini
+1 on comment for the note on not needed to group or aggregate in mysql (didn't know that); on the other point - my tests show you can drop the IF(c.submissionid IS NULL, 0, COUNT(*)) and replace it with COUNT(c.submissionid) (crucial part is to specify the column comming from the left join, otherwise IF IS necessary)
Unreason
+1 for dropping the IF, I will use that in my future queries, ty
Nicolò Martini
A: 

try

SELECT s.loginid, s.title, s.url, s.displayurl, l.username, c.submissionid, 
       COUNT(c.submissionid) AS countComments
FROM submission AS s
INNER JOIN login AS l ON l.loginid = s.loginid
LEFT JOIN comments AS c ON c.submissionid = s.id
GROUP BY s.loginid, s.title, s.url, s.displayurl, l.username, c.submissionid
ORDER BY s.datesubmitted DESC
LIMIT 10

or

SELECT s.loginid, s.title, s.url, s.displayurl, l.username, c.submissionid, 
       (SELECT count(*) FROM submission s WHERE c.submissionid =s.submissionid) AS countComments
FROM submission AS s
INNER JOIN login AS l ON l.loginid = s.loginid
ORDER BY s.datesubmitted DESC
LIMIT 10

providing I didn't make (m)any typos :)

If it works for you I can provide more explanations.

Unreason
I appreciate the help, but I'm still getting blank results for these.
John
You are getting blanks in php? Why don't you run the query directly in mysql to see the exact SQL error message, it'll help :)
Unreason