views:

186

answers:

6

I am trying to search questions which have a given tag.

How can you fix the following problem?

Tables

questions          |     tags
-------------------|-----------------
  question_id      |     tag
  title            |     question_id
  was_sent_at_time |

My code

    SELECT question_id, title
    FROM questions
    WHERE question_id IN
    ( 
        SELECT question_id
        FROM questions
        ORDER BY was_sent_at_time      // problem here
        DESC LIMIT 50
    ) 
    AND tag IN                         // problem here
    (
        SELECT tag FROM tags
        WHERE tag = $1
        AND WHERE question_id IN (                                                                               
            SELECT question_id
            FROM questions
            ORDER BY was_sent_at_time
            DESC LIMIT 50
        )
    )
    ORDER BY was_sent_at_time
    DESC LIMIT 50;

I run and get

Warning: pg_prepare() [function.pg-prepare]: Query failed: ERROR: syntax error at or near "WHERE" LINE 14: AND WHERE question_id IN ( ^ in /var/www/codes/handlers/searches/handle_questions_by_tag.php on line 30

I apparently should be using JOINs. However, I do not want to get tags as an output to my final result.

+1  A: 

JOINS don't mean you will get tags in your final result. You can keep the specified columns the same if you don't want to see tags.

jamesaharvey
+2  A: 

It sounds like you simply want this:

SELECT questions.question_id, questions.title
FROM questions
WHERE EXISTS 
  (SELECT 1 
   FROM tags 
   WHERE tag = $1 AND tags.question_id = questions.question_id
  )
ORDER BY was_sent_at_time DESC
LIMIT 50;

You could also use a JOIN like so:

SELECT questions.question_id, questions.title
FROM questions
INNER JOIN tags ON (tags.question_id = questions.question_id)
GROUP BY questions.question_id
ORDER BY was_sent_at_time DESC
LIMIT 50;

Using a JOIN does not itself determine what rows or columns you get. You determine that by adding the appropriate SQL clauses.

VoteyDisciple
What is 1 in the fourth line in your first code?
Masi
Every `SELECT` statement has to select *something* but since I don't care about any of the fields in that subquery (i.e., I just care that a row exists that matches the `WHERE` clause), I return a constant so MySQL won't have to bother retrieving columns I don't actually intend to use. It could just as easily be 42 or 8347. The 1 itself isn't used anywhere.
VoteyDisciple
+3  A: 

try:

SELECT q.question_id, q.title
    FROM questions      q
        INNER JOIN tags t ON q.question_id=t.question_id
    WHERE tag = $1 
    ORDER BY q.was_sent_at_time
    DESC LIMIT 50
KM
A: 
select questions.* from questions, tags
where questions.questionid = tags.questionid
and tags.tag = $1

However, I suggest a relation many to many between questions and tags (one question can have many tags, one tag can be associated with many questions).

Cătălin Pitiș
A: 
SELECT questions.question_id, questions.title 
FROM questions 
INNER JOIN tags ON questions.question_id=tags.question_id 
WHERE tags.tag=$1 
ORDER BY questions.was_sent_at_time 
DESC LIMIT 50;

I think that will do it...

Jonathan
A: 

How about:

SELECT questions.question_id, questions.title, questions.was_sent_at_time
FROM questions
JOIN tags ON questions.question_id = tags.question_id
WHERE tags.tag = 'whatever'
ORDER BY questions.was_sent_at_time

This shouldn't require anything from the tags table in the output, though I haven't actually tested this.

Dan