ВИБІР із кількома умовами WHERE в одному стовпці


78

Гаразд, я думаю, я маю тут не помітити щось очевидне / просте ... але мені потрібно написати запит, який повертає лише записи, що відповідають кільком критеріям в одному стовпці ...

Моя таблиця - це дуже проста установка посилань для застосування прапорів до користувача ...

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'...

але ... це нічого не повертає ... Що я тут роблю не так?


2
Це твердження не працює, оскільки прапорець не може одночасно дорівнювати "Добровольця" та "Завантажити". Ви можете використовувати оператор АБО замість І, і він буде працювати.
Джохар Заман

Відповіді:


97

Ви можете використовувати 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'

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


1
Проблема з JOINs полягає в тому, що якщо є більше одного запису контакту, пов’язаного з прапором "Завантажено", то будуть посилання на посилання T1.
OMG Ponies

ВИБЕРІТЬ contact_id ІЗ вашої_таблиці ДЕ (прапорець IN ('Волонтер', 'Завантажено', ...) та one_type = somethingype_one) І позначення IN ('someOtherVolunteer', 'Завантажено', ...) та second_type = somethingype_two ГРУПА ПО contact_id МАЄ COUNT (*) = 2 Сер, у мене такий самий сенаріо, як і у вищезазначеному запиті, але він повертає нуль. нульові ряди.
Бангаш

У разі самостійного приєднання для N кількості значень вам знадобиться N самостійного приєднання. У цьому прикладі, що якщо вам доведеться отримати результати з усіма трьома прапорцями "Завантажено", "Волонтер" та "Через імпорт"? Отже, я думаю, що використання GROUP BYз HAVING COUNTмає більше сенсу.
Шрі

23

Використання:

  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 та прапора - якщо немає шансів на дублікати, ви можете пропустити DISTINCT із запиту:

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

10

Подумайте про використання INTERSECT так:

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

Я вважаю, що це найбільш логістичне рішення.


Оскільки запитувач позначив тегом mysql, я вважаю, що варто зазначити, що INTERSECT не працює для MySql
linkonabe

6

не бачу вашої таблиці, але прапором не може бути одночасно "Добровольчий" та "Завантажений". Якщо у вас є кілька значень у стовпці, ви можете використовувати

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

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


3

Спробуйте використати цей альтернативний запит:

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;

-1

-2

Змініть І на АБО. Проста помилка. Думайте про це як про звичайну англійську, я хочу вибрати все, що дорівнює тому чи іншому.


-3

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

спробуйте використати ORу своїй заяві ...

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

Це покаже всі записи, які VolunteerАБО, Uploadedале він хоче записи, які ввійшли двічі та мають кожен раз
kero

-3
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
); 

-3

ваш код:

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

не буде працювати, оскільки ви не оголосили назву таблиці. виконання поверне повідомлення про помилку.

і якщо ви хочете, щоб відображалися обидва пошукові запити, ваш код повинен виглядати приблизно так.

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

а не так, оскільки він завжди повертає помилкові SELECT * FROM (your_table_name) WHERE flag = 'Volunteer' AND flag = 'Upload';

Ви також можете це зробити

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

.


-3

Використовуйте це: Наприклад:

select * from ACCOUNTS_DETAILS
where ACCOUNT_ID=1001
union
select * from ACCOUNTS_DETAILS
where ACCOUNT_ID=1002

-5

Іноді не видно деревини для дерев :)

Ваш оригінальний SQL ..

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

Має бути:

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

1
Я не вірю, що це поверне результати, яких бажав OP. Ідентифікатори контактів повинні відповідати ВСІМ прапорам, а не одному чи кільком із них.
Кілдарефларе
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.