在同一列上使用多个WHERE条件进行选择


77

好的,我想我可能会忽略一些显而易见的/简单的事情...但是我需要编写一个查询,该查询仅返回与同一列上的多个条件匹配的记录...

我的表是一个非常简单的链接设置,用于将标志应用于用户...

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都被标记为“志愿者”和“已上传” ...

我需要做的是返回仅与通过搜索表单输入的多个条件相匹配的那些contactid ... contactid必须与所有选择的标志匹配...在我看来,SQL应该类似于:

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

但是...什么也没返回...我在这里做错了什么?


2
该语句不起作用,因为标志不能同时等于“ Volunteer”和“ Upload”。您可以使用OR运算符代替AND,它将起作用。
Johar Zaman

Answers:


96

您可以使用GROUP BYHAVING 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
JOIN的问题是,如果有多个与“ Uploaded”标志关联的contactid记录,则T1引用将重复。
OMG小马

从your_table中选择contact_id(标志IN('Volunteer','Uploaded',...)and one_type = sometype_one)AND标志IN('someOtherVolunteer','Uploaded',...)和second_type = sometype_two GROUP BY contact_id HAVING COUNT(*)= 2先生,我有与上述查询相同的senario,但返回的是null。零行。
Bangash

如果是自联接,则对于N个值,您将需要N个自联接。在该示例中,如果必须在其中包含所有三个标志“ Uploaded”,“ Volunteer”和“ Via Import”的情况下怎么办?因此,我认为使用GROUP BYwithHAVING COUNT更有意义。
斯里兰卡:

21

使用:

  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
不适

6

不能真正看到您的表格,但标志不能同时是'Volunteer'和'Uploaded'。如果一列中有多个值,则可以使用

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;


-2

将AND更改为OR。简单的错误。认为它像普通的英语一样,我想选择与之相等的任何东西。


-3

AND仅当同时出现在列中时volunteeruploaded才会为您返回答案。否则它将返回null值...

尝试OR在您的陈述中使用...

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

这将显示所有Volunteer或为OR的条目,Uploaded但他希望输入两次且各一次的条目
kero 2013年

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

而不是这样,因为它将始终返回false SELECT * FROM(your_table_name)WHERE标志='志愿者'AND标志='已上传';

你也可以这样做

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

(升序为升序,如果希望它以降序显示,也可以将其更改为desc)



-5

有时您看不到树木的木头:)

您的原始SQL ..

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

应该:

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

1
我认为这不会返回OP所需的结果。contactId需要匹配所有标志,而不是一个或多个。
Kildareflare
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.