[EMAIL PROTECTED] wrote on 01/11/2006 02:42:27 PM:

> Hi List!
> 
> Please forgive me if I'm asking the wrong list (and please guide me to
> the right place).
> 
> I have two tables (simplified for this example) "pics" and "tags" like 
so:
> 
> pics:
> picid   photo
> 1    Mustang
> 2    Apple
> 3    Rock
> 4    Beetle
> 
> tags:
> tagid  picid    tag
> 1        1         Car
> 2        1         Red
> 3        2         Red
> 4        3         Quartz
> 5        4         Car
> 6        2         Food
> 7        1         1979
> 
> I'm trying to craft a query which will join the tables by the picid
> column and return the entries which match multiple "tags". For
> instance I want to query for items that are both "red" and "car" (to
> get the records: Mustang and Beetle in this case).
> 
> I assume I should start with something like:
> 
> SELECT * FROM pics JOIN tags ON pics.picid=tags.tagid WHERE  .....
> 
> and that's where I get stuck. tag="red" AND tag="car" isn't right and
> neighter is tag="red" OR tag="car".
> 
> I think this should be simple ... but I'm too new to SQL. I've messed
> around with GROUPs, UNIONs, etc. but I'm just out of my league. Can
> someone help, or point me to a good tutorial/explanation that would
> help?
> 
> Thanks!
> 
> MikeMartin
> 

One way to do this is to run a query that counts how many tags that belong 
to a picture match your list of criteria. Run this and you will see how 
many pictures have either or both of the tags you are looking for:

SELECT p.id, count(t.tagid) matches
FROM pics p
LEFT JOIN tags t
    ON p.picid = t.picid
    AND t.tag in ('red','car')
GROUP by p.id;

There are three ways to declare which rows of data participate in a query: 
The ON clauses of your JOINs, the WHERE clause, and the HAVING clause. 
JOINs are evaluated first and define what you want the query to look at as 
its source data. The WHERE clause refines the rows identified by the JOINs 
so that you continue evaluation with only those rows you want. The GROUP 
BY is the next part of the query to be evaluated next. That means you 
can't WHERE the results of a GROUP BY. The GROUP BY is where you count how 
many matches you had so we need to use the third option, the HAVING 
clause, to limit your results to just those pics with 2 matches against 
your 2 search terms. Against your simplified tables, the query looks like 
this:

SELECT p.id, count(t.tagid) matches
FROM pics p
LEFT JOIN tags t
    ON p.picid = t.picid
    AND t.tag in ('red','car')
GROUP by p.id
HAVING matches=2;

There are other ways to solve this type of query problem but they suffer 
from the inability to scale easily to multiple terms. If you need to match 
2 of 3 terms, just put all three terms in the ON clause and leave the 
HAVING clause to look for just 2 matches. This pattern is very flexible 
and simple to learn.

Hope this helped,

Shawn Green
Database Administrator
Unimin Corporation - Spruce Pine

Reply via email to