Выбор с несколькими условиями WHERE в одном столбце


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

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

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

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

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

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

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

11 53

11 ответов:

можно использовать 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 уникально).

или использовать Join:

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'

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

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

  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 - если нет никаких шансов на дубликаты, вы можете опустить отличное от запроса:

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

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

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

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

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

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

не очень применимо, видя отформатированную таблицу.

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

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;

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

SELECT contactid, Count(*) 
FROM <YOUR_TABLE> WHERE flag in ('Volunteer','Uploaded')  
GROUP BY contactid 
HAVING count(*)>1;

AND вернет вам ответ только тогда, когда оба volunteer и uploaded присутствуют в вашей колонке. В противном случае он вернется null значение...

попробуйте использовать OR в своем заявлении ...

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

иногда вы не можете видеть лес за деревьями :)

ваш исходный SQL ..

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

должно быть:

SELECT contactid 
 WHERE flag = 'Volunteer' 
   OR flag = 'Uploaded'...
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
); 

код :

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

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

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

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

и не такой, потому что он всегда будет возвращать false Выберите * FROM (your_table_name) где flag = 'волонтер' и flag = 'загружено';

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

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

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