ВЫБОР с несколькими условиями WHERE в одном столбце - PullRequest
60 голосов
/ 29 октября 2010

Хорошо, я думаю, что я мог бы пропустить что-то очевидное / простое здесь ... но мне нужно написать запрос, который возвращает только записи, которые соответствуют нескольким критериям в одном столбце ...

Моя таблицаочень простая настройка связывания для применения флагов к пользователю ...

ID   contactid  flag        flag_type 
-----------------------------------
118  99         Volunteer   1 
119  99         Uploaded    2 
120  100        Via Import  3 
121  100        Volunteer   1  
122  100        Uploaded    2

и т. д. ... в этом случае вы увидите, что оба контакта 99 и 100 помечены как "Волонтер" и "Загружен"...

Что мне нужно сделать, это вернуть ТОЛЬКО те контактные данные, которые соответствуют нескольким критериям, введенным через форму поиска ... контактные должны соответствовать ВСЕ выбранные флаги ... в моей голове SQLдолжно выглядеть примерно так:

SELECT contactid 
 WHERE flag = 'Volunteer' 
   AND flag = 'Uploaded'...

но ... это ничего не возвращает ... Что я здесь не так делаю?

Ответы [ 12 ]

77 голосов
/ 29 октября 2010

Вы можете использовать GROUP BY и HAVING COUNT(*) = _:

SELECT contact_id
FROM your_table
WHERE flag IN ('Volunteer', 'Uploaded', ...)
GROUP BY contact_id
HAVING COUNT(*) = 2 -- // must match number in the WHERE flag IN (...) list

(при условии contact_id, flag уникален).

Или используйте соединения:

SELECT T1.contact_id
FROM your_table T1
JOIN your_table T2 ON T1.contact_id = T2.contact_id AND T2.flag = 'Uploaded'
-- // more joins if necessary
WHERE T1.flag = 'Volunteer'

Если список флагов очень длинный и имеется много совпадений, первое, вероятно, быстрее. Если список флагов короткий, а совпадений мало, вы, вероятно, обнаружите, что второй быстрее. Если производительность вызывает беспокойство, попробуйте протестировать обе эти данные, чтобы увидеть, какие из них работают лучше.

17 голосов
/ 29 октября 2010

Использование:

  SELECT t.contactid
    FROM YOUR_TABLE t
   WHERE flag IN ('Volunteer', 'Uploaded')
GROUP BY t.contactid
  HAVING COUNT(DISTINCT t.flag) = 2

Ключевым моментом является то, что подсчет t.flag должен равняться количеству аргументов в предложении IN.

Использование COUNT(DISTINCT t.flag) происходит в том случае, если нет уникального ограничения на комбинацию contactid и flag - если нет вероятности дублирования, вы можете опустить DISTINCT из запроса:

  SELECT t.contactid
    FROM YOUR_TABLE t
   WHERE flag IN ('Volunteer', 'Uploaded')
GROUP BY t.contactid
  HAVING COUNT(t.flag) = 2
9 голосов
/ 29 марта 2017

Рассмотрите вариант использования INTERSECT следующим образом:

SELECT contactid WHERE flag = 'Volunteer' 
INTERSECT
SELECT contactid WHERE flag = 'Uploaded'

Я думаю, что это наиболее логистическое решение.

4 голосов
/ 29 октября 2010

действительно не может видеть вашу таблицу, но флаг не может быть одновременно «Волонтер» и «Загружен».Если у вас есть несколько значений в столбце, вы можете использовать

WHERE flag LIKE "%Volunteer%" AND flag LIKE "%UPLOADED%"

, что неприменимо для просмотра отформатированной таблицы.

3 голосов
/ 03 февраля 2014

Попробуйте использовать этот альтернативный запрос:

SELECT A.CONTACTID 
FROM (SELECT CONTACTID FROM TESTTBL WHERE FLAG = 'VOLUNTEER')A , 
(SELECT CONTACTID FROM TESTTBL WHERE FLAG = 'UPLOADED') B WHERE A.CONTACTID = B.CONTACTID;
0 голосов
/ 27 февраля 2019

Используйте это: Например:

select * from ACCOUNTS_DETAILS
where ACCOUNT_ID=1001
union
select * from ACCOUNTS_DETAILS
where ACCOUNT_ID=1002
0 голосов
/ 03 августа 2016

ваш код:

SELECT contactid 
WHERE flag = 'Volunteer' AND flag = 'Uploaded' [...]

не будет работать, так как вы не объявили имя таблицы.выполнение вернет сообщение об ошибке.

, и если вы хотите, чтобы отображались оба поисковых запроса, ваш код должен выглядеть примерно так.

SELECT * FROM (your_table_name) WHERE flag = 'Volunteer' OR flag = 'Uploaded';

и не так, потому что он всегда будет возвращатьсяfalse SELECT * FROM (your_table_name) WHERE flag = 'Volunteer' И flag = 'Uploaded';

вы также можете сделать это

SELECT * FROM (your_table_name) 
WHERE flag = 'Volunteer' OR flag = 'Uploaded' 
ORDER BY contactid, flag asc; 

(в порядке возрастания, вы также можете изменитьесли хотите, чтобы он отображался в порядке убывания)

0 голосов
/ 24 июня 2016

Измените И на ИЛИ.Простая ошибкаДумайте об этом как о простом английском, я хочу выбрать что-нибудь с тем, что равно тому или другому.

0 голосов
/ 09 мая 2016
select purpose.pname,company.cname
from purpose
Inner Join company
on purpose.id=company.id
where pname='Fever' and cname='ABC' in (
  select mname
  from medication
  where mname like 'A%'
  order by mname
); 
0 голосов
/ 06 августа 2015
SELECT contactid, Count(*) 
FROM <YOUR_TABLE> WHERE flag in ('Volunteer','Uploaded')  
GROUP BY contactid 
HAVING count(*)>1;
...