与SQL查询相混淆

时间:2019-05-02 10:56:44

标签: sql database

假设我们有一个聊天应用程序数据库:

CREATE TABLE Users (uid int PRIMARY KEY, name text, phone text );

CREATE TABLE Messages (recipient int REFERENCES Users(uid), sender int 
REFERENCES Users(uid), time timestamp NOT NULL, message text NOT NULL, 
PRIMARY KEY (recipient, sender, time));

我想查找至少两个不同的用户对之间已发送的所有消息。例如,如果消息“ Hello”是从用户1发送的 用户2以及从用户75到用户83,则必须将其显示在结果中。但是,如果仅在用户1和用户2之间发送了它,则不应在结果中显示它。

我考虑将至少出现两次的所有消息分组如下:

SELECT message 
FROM Messages 
GROUP BY message 
HAVING COUNT(*) > 1

但是,这将无济于事,因为同一对用户可能一次又一次发送相同的消息。我可以同时按发件人,收件人和邮件分组吗?如果是的话,这将给我带来什么?

此外,有没有一种方法可以让我轻松地用随机值填充这两个表并亲自进行查询以检查它们?

谢谢!

4 个答案:

答案 0 :(得分:2)

是的,首先将用户1,用户2和消息分组。这会给您每对唯一的消息:

SELECT case when recipient > sender then recipient else sender end user1,
       case when recipient > sender then sender else recipient end user2,
       message 
FROM Messages 
GROUP BY user1, user2, message

然后通过Message从该结果组中返回,并且仅返回大于1的计数。您可以使用嵌套查询来执行此操作:

SELECT message, COUNT(message) 
FROM (SELECT case when recipient > sender then recipient else sender end user1,
            case when recipient > sender then sender else recipient end user2,
            message 
     FROM Messages 
     GROUP BY user1, user2, message) PairMessages 
GROUP BY message 
HAVING COUNT(message) > 1

也许以此作为测试开始:

INSERT INTO Users VALUES (1,'john',1111111111)
INSERT INTO Users VALUES (2,'paul',2222222222)
INSERT INTO Users VALUES (75,'george',7575757575)
INSERT INTO Users VALUES (83,'ringo',8383838383)
INSERT INTO Messages VALUES (2,1,GETDATE(),'Yesterday')
INSERT INTO Messages VALUES (1,2,GETDATE(),'hello')
INSERT INTO Messages VALUES (75,83,GETDATE(),'yellow')
INSERT INTO Messages VALUES (75,83,GETDATE(),'hello')

在超过1对用户之间发送消息时,您应该能够打招呼。

编辑:我用正确的答案更新了上面的内容,以显示每对用户对每条消息都是唯一的。同样,为每对用户创建一个groupID可能是一个好主意。然后,您可以将任意数量的用户添加到该groupID。请参阅此处以了解想法:http://sqlfiddle.com/#!9/fbc2e2/3

答案 1 :(得分:2)

这将适用于MySql:

SELECT message 
FROM Messages 
GROUP BY message 
HAVING 
  COUNT(distinct least(recipient, sender), greatest(recipient, sender)) > 1

请参见demo

答案 2 :(得分:1)

最简单的方法是使用以下查询:

select message, count(*)
from Messages
group by message
HAVING COUNT(distinct least(recipient, sender), greatest(recipient, sender)) > 1

通过添加该消息的使用次数,可以改善forpas的查询。

答案 3 :(得分:0)

您可以使用EXISTS进行过滤:

SELECT m.message 
FROM Messages m
WHERE EXISTS (SELECT 1
              FROM Messages m2
              WHERE m2.message = m.message AND
                    m2.recipient NOT IN (m.recipient, m.sender) AND
                    m2.sender NOT IN (m.recipient, m.sender)
             )       
GROUP BY m.message ;

EXISTS检查具有相同消息的另一行是否具有不同的用户对。