Предположим, у нас есть база данных для приложения чата:
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 ответа
Да, сначала начните с группировки user1, user2 и сообщения. Это дает вам уникальное сообщение для каждой пары:
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')
Вы должны иметь возможность получить привет, поскольку ваше сообщение отправлено между более чем одной парой пользователей.
Изменить: я обновил выше с правильным ответом, чтобы показать, что каждая пара пользователей уникальна для каждого сообщения. Кроме того, может быть хорошей идеей создать groupID для каждой пары пользователей. Затем вы можете добавить столько пользователей, сколько вы хотите к этому groupID. Смотрите здесь для идеи: http://sqlfiddle.com/#!9/fbc2e2/3 а>
Самый простой способ добиться этого - использовать следующий запрос:
select message, count(*)
from Messages
group by message
HAVING COUNT(distinct least(recipient, sender), greatest(recipient, sender)) > 1
Это улучшает запрос forpas, добавляя количество раз, когда это сообщение использовалось.
Вы можете использовать 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
проверяет, что другая строка с тем же сообщением имеет другую пару пользователей.
Это будет работать для MySql:
SELECT message
FROM Messages
GROUP BY message
HAVING
COUNT(distinct least(recipient, sender), greatest(recipient, sender)) > 1
Похожие вопросы
Связанные вопросы
Новые вопросы
sql
Язык структурированных запросов (SQL) - это язык запросов к базам данных. Вопросы должны включать примеры кода, структуру таблицы, примеры данных и тег для используемой реализации СУБД (например, MySQL, PostgreSQL, Oracle, MS SQL Server, IBM DB2 и т. Д.). Если ваш вопрос относится исключительно к конкретной СУБД (использует определенные расширения / функции), используйте вместо этого тег этой СУБД. Ответы на вопросы, помеченные SQL, должны использовать стандарт ISO / IEC SQL.