I’m trying to write a SQL statement that will allow me to select a series of articles from a table based on their keywords. What I’ve got so far is a token table, an article table, and a many-to-many table for tokens & articles:
tokens
rowid
token
token_article
token_rowid
article_rowid
articles
rowid
What I’m doing is taking a search query, splitting it up by spaces, then select all articles that contains those keywords. So far I’ve come up with this:
select * from
(select * from tokens
inner join token_article on
tokens.rowid = token_article.token_rowid and
token = 'ABC'
) as t1,
(select * from tokens
inner join token_article on
tokens.rowid = token_article.token_rowid and
token = 'DEF'
) as t2
where t1.article_rowid = t2.article_rowid and t2.article_rowid = articles.rowid
Which works but of course its doing a select on all articles that match ABC and all articles that DEF then selecting them.
Now I’m trying to figure out a better way. What I imagine in my mind that would work would be to select all the articles that match ABC and from those match any with DEF. This is what I imagine it to look like but does not work (receive error message “no such columns: tokens.rowid”)
select * from
(select * from
(select * from tokens
inner join token_article on
tokens.rowid = token_article.token_rowid and
token = 'ABC'
)
inner join token_article on
tokens.rowid = token_article.token_rowid and
token = 'DEF'
)
Because there is more than one way to do this…this method uses GROUP BY and HAVING clauses. The query is looking for all articles that have either the ABC or DEF token, but then grouping by the article ID where the count of tokens for the article is equal to the number of tokens being queried.
Note that I’ve used MSSQL syntax here, but the concept should work in most SQL implementations.
Edit: I should point out that this has a fairly clean syntax as you add more tokens to the query. If you add more tokens, then you just need to modify the
t.token_incriteria and adjust theHAVING COUNT(*) = xclause accordingly.