Kevin Waterson wrote:
This one time, at band camp, Baron Schwartz <[EMAIL PROTECTED]> wrote:

I wish to select all bookmark_title and bookmark_url that have the same 
keywords as
the bookmark_url 'http://www.redhat.com. I do this..
mysql> SELECT child.bookmark_id, child.bookmark_title, child.bookmark_url FROM 
bookmarks AS child join bookmarks AS parent ON parent.bookmark_keyword = 
child.bookmark_keyword WHERE child.bookmark_url='http://www.redhat.com' GROUP BY 
child.bookmark_keyword;

That query is right.

But this returns..
+-------------+----------------+-----------------------+
| bookmark_id | bookmark_title | bookmark_url          |
+-------------+----------------+-----------------------+
|           4 | and four       | http://www.redhat.com |
|           8 | finally        | http://www.redhat.com |
+-------------+----------------+-----------------------+
But, the JOIN table from which those columns come actually has the columns you want from the parent table as well. It's just that you're selecting the child columns.

Im not sure I follow, the results should be those with id's of 1, 3, 4, 5, 6, 
7, 8

and If I chose http://www.php.net that has only the keyword of "php" then the 
results
would be 1,3,5, and 8

Right. I misspoke slightly: the JOIN is right, but the SELECT list is not. Look again at your query:

SELECT child.bookmark_id, child.bookmark_title, child.bookmark_url
... WHERE child.bookmark_url='http://www.redhat.com'

Do you see why all your results have a bookmark_url of http://www.redhat .com? It's because you are selecting the columns from the *child* table and at the same time your WHERE clause guarantees the *child* table will ONLY have that URL. Keep looking at the WHERE clause and the select list until you see it. I'm highlighting it again below with -->ARROWS<--

SELECT ... -->CHILD<--.bookmark_url ...
... WHERE -->CHILD<--.bookmark_url ...

Do you see, child.bookmark_url is a *constant* in your query, in both the SELECT list and the WHERE clause?

The steps in the JOIN are conceptually like this:

1) find the rows in child that match the WHERE clause.
2) find matching rows in parent.
3) put them side-by-side.
4) choose columns from the result.
5) GROUP BY.

I'll abbreviate the table so it won't wrap and mess up the diagram I'm about to create.

create table bookmarks(bookmark_url varchar(50), bookmark_keyword varchar(50));

insert into bookmarks(bookmark_url, bookmark_keyword)
 values
 ('http://www.redhat.com', 'linux'),
 ('http://www.redhat.com', 'php'),
 ('http://www.ez.no', 'php'),
 ('http://www.phpro.org', 'php'),
 ('http://www.youtube.com', 'linux');

Here's a slightly altered query, essentially the same thing:

SELECT child.bookmark_url as cbu, child.bookmark_keyword as cbk,
       parent.bookmark_url as pbu, parent.bookmark_keyword as pbk
FROM bookmarks AS child
   JOIN bookmarks AS parent
      ON parent.bookmark_keyword = child.bookmark_keyword
WHERE child.bookmark_url='http://www.redhat.com';

Imagine what the table looks like after step 3:

+-----------------------+-------+------------------------+-------+
| cbu                   | cbk   | pbu                    | pbk   |
+-----------------------+-------+------------------------+-------+
| http://www.redhat.com | linux | http://www.redhat.com  | linux |
| http://www.redhat.com | php   | http://www.redhat.com  | php   |
| http://www.redhat.com | php   | http://www.ez.no       | php   |
| http://www.redhat.com | php   | http://www.phpro.org   | php   |
| http://www.redhat.com | linux | http://www.youtube.com | linux |
+-----------------------+-------+------------------------+-------+

Do you see how the columns from the child are on the left, and the columns from the parent are on the right? Your WHERE clause holds the columns on the left constant, and that is what you are selecting from this intermediate table! You need to select from the right-hand columns:

SELECT parent.bookmark_url as pbu, parent.bookmark_keyword as pbk
FROM bookmarks AS child
   JOIN bookmarks AS parent
      ON parent.bookmark_keyword = child.bookmark_keyword
WHERE child.bookmark_url='http://www.redhat.com';

+------------------------+-------+
| pbu                    | pbk   |
+------------------------+-------+
| http://www.redhat.com  | linux |
| http://www.redhat.com  | php   |
| http://www.ez.no       | php   |
| http://www.phpro.org   | php   |
| http://www.youtube.com | linux |
+------------------------+-------+

I didn't change the JOIN a bit; I only changed which columns I'm extracting from this intermediate table.

You have one final problem, which isn't really causing you trouble with THIS query, but will likely bite you in the future: you are selecting non-grouped columns in a GROUP BY query. I'll refer you to something I wrote about that. You can read it at your leisure.

http://www.xaprb.com/blog/2006/03/11/many-to-one-problems-in-sql/

I hope this helps.

Baron

--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to