查找一列中具有相同值而另一列中具有其他值的行? [英] Find rows that have same value in one column and other values in another column?

查看:116
本文介绍了查找一列中具有相同值而另一列中具有其他值的行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个PostgreSQL数据库,将用户存储在 users 表中,并将他们参与的对话存储在 conversation 表中。由于每个用户可以参与多个对话,并且每个对话可以涉及多个用户,因此我有一个 conversation_user 链接表来跟踪哪些用户正在参与每个对话:

I have a PostgreSQL database that stores users in a users table and conversations they take part in a conversation table. Since each user can take part in multiple conversations and each conversation can involve multiple users, I have a conversation_user linking table to track which users are participating in each conversation:

# conversation_user
id  |  conversation_id | user_id
----+------------------+--------
1   |                1 |      32
2   |                1 |       3
3   |                2 |      32
4   |                2 |       3
5   |                2 |       4

在上表中,用户32仅与用户3进行一次对话,而与用户3进行另一次对话和用户4。我该如何写一个查询来显示仅用户32和用户3之间存在对话?

In the above table, user 32 is having one conversation with just user 3 and another with both 3 and user 4. How would I write a query that would show that there is a conversation between just user 32 and user 3?

我尝试了以下操作:

SELECT conversation_id AS cid,
       user_id
FROM conversation_user
GROUP BY cid HAVING count(*) = 2
AND (user_id = 32
     OR user_id = 3);

SELECT conversation_id AS cid,
   user_id
FROM conversation_user
GROUP BY (cid HAVING count(*) = 2
AND (user_id = 32
     OR user_id = 3));

SELECT conversation_id AS cid,
       user_id
FROM conversation_user
WHERE (user_id = 32)
  OR (user_id = 3)
GROUP BY cid HAVING count(*) = 2;

这些查询会引发错误,指出user_id必须出现在 GROUP BY中子句或在聚合函数中使用。将它们放在汇总函数中(例如 MIN MAX )听起来不太合适。我以为我的前两次尝试是将它们放在 GROUP BY 子句中。

These queries throw an error that says that user_id must appear in the GROUP BY clause or be used in an aggregate function. Putting them in an aggregate function (e.g. MIN or MAX) doesn't sound appropriate. I thought that my first two attempts were putting them in the GROUP BY clause.

我在做什么错了?

推荐答案

关系划分。在这个相关的问题下,我们组装了一系列技术:

This is a case of relational division. We have assembled an arsenal of techniques under this related question:

  • How to filter SQL results in a has-many-through relation

特殊的困难是排除其他用户。基本上有4种技术。

The special difficulty is to exclude additional users. There are basically 4 techniques.

  • Select rows which are not present in other table

左联接 / IS空 c:

SELECT cu1.conversation_id
FROM        conversation_user cu1
JOIN        conversation_user cu2 USING (conversation_id)
LEFT   JOIN conversation_user cu3 ON cu3.conversation_id = cu1.conversation_id
                                 AND cu3.user_id NOT IN (3,32)
WHERE  cu1.user_id = 32
AND    cu2.user_id = 3
AND    cu3.conversation_id IS NULL;

不存在

SELECT cu1.conversation_id
FROM   conversation_user cu1
JOIN   conversation_user cu2 USING (conversation_id)
WHERE  cu1.user_id = 32
AND    cu2.user_id = 3
AND NOT EXISTS (
   SELECT 1
   FROM   conversation_user cu3
   WHERE  cu3.conversation_id = cu1.conversation_id
   AND    cu3.user_id NOT IN (3,32)
   );

两个查询都依赖于 UNIQUE (conversation_id,user_id)约束,该约束可能存在也可能没有。这意味着,对于同一对话,如果多次列出 user_id 32(或3),该查询甚至可以工作。不过,您在结果中得到重复的行,并且需要应用 DISTINCT GROUP BY

唯一的条件是您制定的条件:

Both queries do not depend on a UNIQUE constraint for (conversation_id, user_id), which may or may not be in place. Meaning, the query even works if user_id 32 (or 3) is listed more than once for the same conversation. You would get duplicate rows in the result, though, and need to apply DISTINCT or GROUP BY.
The only condition is the one you formulated:


...一条查询将显示仅在用户32和用户3之间存在对话?

... a query that would show that there is a conversation between just user 32 and user 3?



经审核的查询



您在评论中链接的查询不起作用。您忘记了排除其他参与者。应该是这样的:

Audited query

The query you linked in the comment wouldn't work. You forgot to exclude other participants. Should be something like:

SELECT *  -- or whatever you want to return
FROM   conversation_user cu1
WHERE  cu1.user_id = 32
AND    EXISTS (
   SELECT 1
   FROM   conversation_user cu2
   WHERE  cu2.conversation_id = cu1.conversation_id 
   AND    cu2.user_id = 3
   )
AND NOT EXISTS (
   SELECT 1
   FROM   conversation_user cu3
   WHERE  cu3.conversation_id = cu1.conversation_id
   AND    cu3.user_id NOT IN (3,32)
   );

与其他两个查询类似,但是如果<$ c不会返回多行$ c> user_id = 3 已链接多次。

Which is similar to the other two queries, except that it will not return multiple rows if user_id = 3 is linked multiple times.

这篇关于查找一列中具有相同值而另一列中具有其他值的行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆