views:

203

answers:

2

I'm trying to select all fields in two separate tables as long as they're sharing a common ID.

//mysql query
$result = mysql_query("SELECT * FROM project, links 
WHERE project.id = links.id and project.id = $clientID")

//displaying the link 
if ($row['url'] != null){
    echo "<div class='clientsection' id='links'>Links</div>";
    echo "<a class='clientlink' id='link1' href='" . $row['url'] . "'>" . $row['name'] . "</a>";
}
else {
echo "<a class='clientlink' id='link1' href='" . $row['url'] . "' style='display:none;'>" . $row['name'] . "</a>";
        };

As you can see, my tables are "projects", and "links" Each is sharing a common field "id" for reference. It looks as though where both links.id and project.id are equal, it outputs anything, but when there is no links.id associated with a given $clientID the container relative to the $clientID doesn't display at all.

Essentially I'm using this to add links dynamically to a specific client in this CMS and if there are no links, I want the container to show up anyway.

Hopefully I've expressed myself clearly, any pointers in the right direction are appreciated. Thanks!

+4  A: 

Using the SQL ANSI explicit join syntax, you can specify a LEFT OUTER JOIN, as opposed to the INNER JOIN that you are doing in your implicit join.

The LEFT OUTER JOIN returns results in the first table even if there are no matching rows in the joining table:

SELECT * FROM project
LEFT OUTER JOIN links 
ON links.id = project.id
WHERE project.id = $clientID

For rows where there is no matching id in the links table, links.id will be NULL.

Edit

If you want just the first link, where the autoincrement primary key links.linkid specifies the order, you can do a self join like this:

SELECT * FROM project
LEFT OUTER JOIN links
ON links.id = project.id
LEFT OUTER JOIN links l2
ON l2.id = project.id AND l2.linkid < links.linkid
WHERE project.id = $clientID AND l2.id IS NULL

What this does is join in any links table rows where the linkid is smaller, and then exludes those rows in the WHERE clause. You end up with just the rows where there is no smaller linkid, hence the link with the smallest linkid for each project.

Marcus Adams
Thanks Marcus for your answer, although this has left me with something else to fix. Now, it is opening the correct containers, but on individual client IDs where there is more than one link, it displays multiple containers, with one showing the first link, and then another one created with each subsequent link
Matt Nathanson
@Matt, is there a column in the links table that specifies the order of the links, so that we can find the "first" link?
Marcus Adams
I have a primary key, linkid that is obviously ordered, would that work?
Matt Nathanson
@Matt, I've updated my answer for your second question. This can also be done with a sub query.
Marcus Adams
Hey Marcus, I really appreciate your time. I'm actually looking to display all the links, if there were 100 links for this $clientID i'd want to display all of them.. the edited query you posted actually causes zero links to display..
Matt Nathanson
@Matt, I don't understand because you said that you need to fix "and then another one created with each subsequent link". If you require further help, please better explain the issue with the first query. If the second query is returning zero rows, double check your typing. It should be two LEFT OUTER JOINs.
Marcus Adams
@Marcus, What I'm trying to do is display more 1 or more links IF they exist. If I use your EDITED Query, the container shows up but it doesn't display anything with the links. If I use your original query and the if statement to display the link, and there is more than 1 link, it displays multiple client containers. If I change it to a while loop, it displays only the most recent. Does that make sense?
Matt Nathanson
+1  A: 

You're query is essentially doing an "INNER JOIN" so it will only return records where there is matching id's in both tables. If you do an "LEFT OUTER JOIN" as in Marcus's example it will return the results you are looking for.

Germ