views:

167

answers:

2

This is a complicated situation (for me) that I'm hopeful someone on here can help me with. I've done plenty of searching for a solution and have not been able to locate one. This is essentially my situation... (I've trimmed it down because if someone can help me to create this query I can take it from there.)

TABLE articles (article_id, article_title)

TABLE articles_tags (row_id, article_id, tag_id)

TABLE article_categories (row_id, article_id, category_id)

All of the tables have article_id in common. I know what all of the tag_id and category_id rows are. What I want to do is return a list of all the articles that article_tags and article_categories MAY have in common, ordered by the number of common entries.

For example:

article1 - tags: tag1, tag2, tag3 - categories: cat1, cat2

article2 - tags: tag2 - categories: cat1, cat2

article3 - tags: tag1, tag3 - categories: cat1

So if my article had "tag1" and "cat1 and cat2" it should return the articles in this order:

article1 (tag1, cat1 and cat2 in common)

article3 (tag1, cat1 in common)

article2 (cat1 in common)

Any help would genuinely be appreciated! Thank you!

A: 

Okay, here's my first draft:

 SELECT article_id, count(*) as common_term_count FROM 
      (
      SELECT article_id FROM tags WHERE tag IN 
         (SELECT tag FROM tags WHERE article_id = :YourArticle)
      UNION ALL 
      SELECT article_id FROM categories WHERE category IN
         (SELECT category FROM categories WHERE article_id = :YourArticle)
       ) AS accumulator_table 
 GROUP BY article_id ORDER common_term_count DESC

I think this is valid MySQL syntax.

Larry Lustig
Thank you for your response. Unfortunately, common_term_count always returns 1, but I think it's close. If I take out the UNION and only SELECT from tags, it returns an accurate count. It only returns 1 when a UNION is made. Any thoughts?
Robert Samuel White
I see I have a syntax error, having reversed SELECT and ALL. That could possibly be affecting the results. Will edit and fix.
Larry Lustig
Actually yes, my typo was probably causing the problem. UNION without ALL will cause the removal of all duplicate records in the result set. Since the two UNIONed queries produce all identical rows, that was likely causing the problem. My apologies for taking up your time on that.
Larry Lustig
Not sure why MySQL even ran the query with the typo, I would have expected different numbers of columns in the two UNIONed queries. In my (limited) MySQL experience, it seems to run a lot of queries that I wish it wouldn't.
Larry Lustig
Thanks so much, Larry! That fixed it. I appreciate you taking the time to help me! I spent the time trying to learn more about UNIONs and JOINs -- they have always been rather puzzling to me! You just solved a very needed solution for me. I can't thank you enough! :-)
Robert Samuel White
Always a pleasure to be able to help someone out.
Larry Lustig
A: 

If you would just have the tag table (not the category table) this is a more optimized start:

SELECT article_id,count(*) AS q FROM article_tags WHERE id_tag IN (SELECT id_tag FROM article_tags WHERE article_id=41) AND article_id!=41 GROUP BY article_id ORDER BY q DESC
andufo