Выберите строки, которые содержат более одного условия одновременно - PullRequest
1 голос
/ 27 марта 2009

У меня есть такая структура таблицы:

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

Когда я хочу выбрать строки, содержащие одно или несколько условий, я использую ИЛИ (... КОГДА cond = 2 ИЛИ cond = 6 GROUP BY ID ...)

Но как выбрать строки, содержащие более одного условия, сгруппированные по идентификатору? Например. когда я хочу найти строки, содержащие cond 2 и 6, он возвращает только ID 1

Спасибо

Ответы [ 7 ]

3 голосов
/ 27 марта 2009

Вы можете использовать соединение для этого:

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

Или это, если пары ID / cond уникальны:

SELECT  ID
FROM    tbl
WHERE   cond IN (2, 6)
GROUP BY ID
HAVING COUNT(cond) = 2
2 голосов
/ 27 марта 2009

Есть несколько способов сделать это.

Использование COUNT (самый быстрый):

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

Использование EXISTS (использование вложенных циклов, медленнее на очень больших таблицах, но менее криптографически и более расширяемо, чем вариант COUNT):

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)

Использование GROUP_CONCAT (MySql-специфическая вариация для темы COUNT, но если вам когда-нибудь понадобятся точные совпадения, например, cond = 2 и cond = 6, то нет другого cond, тогда приведенные ниже изменения, измененные на SELECT id, GROUP_CONCAT(DISTINCT cond ORDER BY cond) AS conds ... WHERE conds='2,6', будут выполняться лучший)

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

1 голос
/ 27 марта 2009

Вы можете использовать подзапросы и группу для этого. Предполагая, что вы знаете количество значений, которые вам нужно найти, вы можете сделать это:

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

В общем случае вам просто нужно обновить список условий, которые должны существовать (т. Е. "(2, 6)"), чтобы включить новые значения, а затем обновить предложение, имеющее значение (т. Е. "Имеющее счет (t .cond) = 2 "), чтобы равняться общему количеству значений.

0 голосов
/ 27 марта 2009

Задумывались ли вы об использовании предложения UNION?

ВЫБЕРИТЕ ID ИЗ MyTable ГДЕ КОНД = 2 UNION ВЫБЕРИТЕ ID ИЗ MyTable ГДЕ конд = 6

Было бы также полезно, если бы вы могли указать точный вывод, который вы ищете. Но из того, что я понял, UNION мог бы пойти по этому пути.

0 голосов
/ 27 марта 2009

Это может быть немного более гибким, если на ID нет дуплей.

SELECT id
FROM tbl 
GROUP BY id
HAVING SUM(CASE cond 
    WHEN 2 THEN 1
    WHEN 6 THEN 1
    ELSE 0 END) > 1
0 голосов
/ 27 марта 2009

Вот еще один синтаксис, который немного более прозрачен (хотя и не так эффективен) в отношении того, что он делает.

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)
0 голосов
/ 27 марта 2009
SELECT DISTINCT(ID) WHERE (cond = 2) OR (cond = 6)
...