Question

I have table structure like this:

ID   cond
1    5
1    2
1    6
8    2
9    1
9    5

When I want to select rows that contain one or more conditions i use OR (...WHEN cond=2 OR cond=6 GROUP BY ID...)

But how to select rows that contain more than one condition simultaneously grouped by ID? E.g. when i want to find rows that contain cond 2 and 6, it returns only ID 1

Thanks

Was it helpful?

Solution

There are multiple ways of doing this.

Using COUNT (fastest):

SELECT id FROM tbl WHERE tbl.cond IN ( 2, 6 ) HAVING COUNT(DISTINCT cond) = 2 GROUP BY id

Using EXISTS (using nested loops, slower on very large tables, but less cryptical and more xtensible than the COUNT variant):

SELECT DISTINCT id FROM tbl AS tbl1 WHERE EXISTS (SELECT * FROM tbl AS tbl2 WHERE tbl1.id = tbl2.id AND tbl2.cond = 2) AND EXISTS (SELECT * FROM tbl AS tbl2 WHERE tbl1.id = tbl2.id AND tbl2.cond = 6)

Using GROUP_CONCAT (a MySql specific variation on the COUNT theme, but if you ever want exact matches, e.g. cond=2 and cond=6 an no other cond, then the below, altered to read SELECT id, GROUP_CONCAT(DISTINCT cond ORDER BY cond) AS conds ... WHERE conds='2,6' will perform best)

SELECT id, ','||GROUP_CONCAT(DISTINCT cond)||',' AS conds FROM tbl WHERE INSTR(conds, ',2,') > 0 AND INSTR(conds, ',6,') > 0 GROUP BY id

OTHER TIPS

You can use a join for this:

SELECT  ID
FROM    tbl t1
        INNER JOIN
                tbl t2
                ON t1.ID = t2.ID
WHERE   t1.cond = 2
AND     t2.cond = 6

Or this, if ID/cond pairs are unique:

SELECT  ID
FROM    tbl
WHERE   cond IN (2, 6)
GROUP BY ID
HAVING COUNT(cond) = 2

You could use subqueries and a group to do this. Assuming you know the number of values you need to find, you can do this:

select
    t.ID
from
    (
        select distinct
            ID, cond
        from
            tbl
        where
            tbl.cond in (2, 6)
    ) as t
group by
    t.ID
having
    count(t.cond) = 2

For the general case, you would simply have to update the list of conditions that must exist (i.e. "(2, 6)") to include the new values, and then update the having clause (i.e. "having count(t.cond) = 2") to equal the total number of values.

SELECT DISTINCT(ID) WHERE (cond = 2) OR (cond = 6)

Here's another syntax that is a little more transparent (although not as performant) about what it is doing.

SELECT DISTINCT ID 
FROM MyTable T
WHERE 
  EXISTS(SELECT ID FROM MyTable T1 WHERE Cond=2 AND T1.ID=T.ID) AND
  EXISTS(SELECT ID From MyTable T2 WHERE Cond=6 AND T2.ID=T.ID)

This might be a little more flexable if there are no dups per id.

SELECT id
FROM tbl 
GROUP BY id
HAVING SUM(CASE cond 
    WHEN 2 THEN 1
    WHEN 6 THEN 1
    ELSE 0 END) > 1

Have you thought about using the UNION clause?

SELECT ID FROM MyTable WHERE cond = 2 UNION SELECT ID FROM MyTable WHERE cond = 6

It would also help if you could specify the exact output you are looking for. But from what I understood, UNION would be the way to go.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top