通过匹配值来查找id

时间:2014-05-24 14:04:32

标签: sql relational-division

我有两张桌子,但IMO只有第一张这个问题是必要的。

conversation_id  user 
conv1        randomuser
conv1        admin    
conv2        derp   
conv3        derp   
conv3        admin  
conv3        herp   
conv4        derp   
conv4        admin  

现在,我想通过derpadmin选择conversation_id。 conversation_id应为conv4

我尝试了很多选项,我找到的“最佳”工作是:

SELECT chat_och_users_in_conversation.conversation_id AS conv_id FROM     
chat_och_users_in_conversation  
WHERE USER IN ('derp', 'admin')
GROUP BY conversation_id
HAVING (SELECT COUNT(*) 
        FROM chat_och_users_in_conversation 
        WHERE conversation_id = conv_id ) = 2

返回的conv_id为conv1conv4。我想我明白为什么会这样:IN在匹配的行中就像OR一样。

请注意,这应该适用于许多不同的数据库类型,因此不仅仅是MySQL。

3 个答案:

答案 0 :(得分:0)

如果您的值很少,则可以使用EXISTS / NOT EXISTS

SELECT DISTINCT c1.conversation_id AS conv_id 
FROM   chat_och_users_in_conversation    c1
WHERE EXISTS
(
    SELECT 1 FROM chat_och_users_in_conversation  c2
    WHERE c1.conversation_id = c2.conversation_id
    AND   c2.user = 'derp'
)
AND EXISTS
(
    SELECT 1 FROM chat_och_users_in_conversation  c2
    WHERE c1.conversation_id = c2.conversation_id
    AND   c2.user = 'admin'
)
AND NOT EXISTS
( 
    SELECT 1 FROM chat_och_users_in_conversation  c2
    WHERE c1.conversation_id = c2.conversation_id
    AND   c2.user NOT IN ('derp', 'admin')
)

它冗长而简单(只是复制粘贴)和易于理解。它也可以轻松更改或扩展。

Demo

答案 1 :(得分:0)

不确定您是否想要所有值:

SELECT conversation_id AS conv_id 
FROM chat_och_users_in_conversation  
WHERE USER IN ('derp', 'admin')
GROUP BY conversation_id
HAVING COUNT(DISTINCT USER) = 2

或者只是最后一个?

SELECT MAX(conversation_id) AS conv_id 
FROM chat_och_users_in_conversation  
WHERE USER IN ('derp', 'admin')
GROUP BY conversation_id
HAVING COUNT(DISTINCT USER) = 2

答案 2 :(得分:0)

试一试

SELECT DISTINCT a1.conversation_id  
from chat_och_users_in_conversation  a1 JOIN chat_och_users_in_conversation  a2 on a1.conversation_id  = a2.conversation_id  
WHERE a1.user <> a2.user and a1.User in ('derp') and a2.user in ('admin')

如果您要与admin和derp以外的其他人排除对话

with cte as(
SELECT DISTINCT a1.conversation_id  cid
from chat_och_users_in_conversation  a1 
JOIN chat_och_users_in_conversation  a2 on a1.conversation_id  = a2.conversation_id  
WHERE a1.[user] <> a2.[user] and a1.[User] in ('derp') and a2.[user] in ('admin')
)
select * from cte where cid not in (select a3.conversation_id from chat_och_users_in_conversation a3 where a3.[user] 
                                       NOT IN ('derp','admin'))