2

I have this array:

$results = array('1', '3', '123')

and this table:

id  |  item  |  tag
1      1        1
2      1        3
3      1        123
4      2        1
5      3        1
6      4        3

I want to perform a query like this:

SELECT item FROM table WHERE ALL 3 TAGS OF THE ARRAY EXIST.

In the example I want to return only Item=1, because it's the only Item with all 3 tags of the array.

So far I have this:

$query .= " SELECT item FROM #__table WHERE tag IN ('";
$query .= implode("','",$results); 
$query .= "')"; 

But it does not return the correct Items, instead it returns all items that are related at least with one element of the array.

4
  • What does it return? Do you get an error? Or "just" an empty result? Commented Feb 15, 2012 at 21:39
  • Do you really wish for them to match simply by them existing, or should your array be logically related to each of the table columns? (item, id, tag) Commented Feb 15, 2012 at 21:41
  • @Cassy It just returns all items that have at least one of the elements of the array. Commented Feb 15, 2012 at 21:42
  • @hexparrot I am sorry I don't understand your question. I want to return only the items that are related in the table with all 3 tags in the array. Commented Feb 15, 2012 at 21:43

3 Answers 3

6

To make the IN work as an AND instead of an OR, you use a HAVING clause to make sure that you get the same number of distinct values returned as exist in the IN clause.

SELECT item
    FROM YourTable
    WHERE tag IN ('1', '3', '123')
    GROUP BY item
    HAVING COUNT(DISTINCT tag) = 3
Sign up to request clarification or add additional context in comments.

3 Comments

What if the count of the elements in the array is dynamic and not always 3? Should it be HAVING COUNT(DISTINCT tag) = count($results) ?
@yann: The value you test in the HAVING clause must be equal to the number of elements in the array.
If there are no duplicate tags for a particular item (in other words, if there is a unique constraint on (item, tag)), then you don't need DISTINCT.
4

An IN clause is basically just a shortcut for writing out a long or chain, e.g.

... WHERE a IN (1,2,3)

is the same as

... WHERE (a = 1) or (a = 2) or (a = 3)

If you require that ALL of the values in the IN clause be present, you can't use a basic IN clause. There's no WHERE IN ALL (...) type construct in MySQL.

You can simulate it with a subquery:

SELECT *
FROM yourtable
WHERE id IN (
    SELECT DISTINCT id
    FROM yourtable
    WHERE tag IN (1,3,123)
    GROUP BY id
    HAVING (COUNT(tag) = 3)
);

The inner query fetches all IDs where all three tag values are present, then the outer query uses the inner results to fetch the full record.

1 Comment

Shouldn't the inner query group on item, not, id?
1

SQL:

SELECT item FROM table WHERE tag IN (1,3,123) GROUP BY item HAVING COUNT(DISTINCT tag) = 3;

PHP:

$query = sprintf('SELECT item FROM table WHERE tag IN (%s) GROUP BY item HAVING COUNT(DISTINCT tag) = %d',
    implode(',', $results),
    count($results));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.