在私人消息中存储用户之间对话框的最佳表结构是什么? 每个用户都可以向许多接收者发送个人信息。 每封邮件都有发件人标志:是否删除了邮件 每条消息都有接收者标志:消息未读,已读或已删除 每条消息都可以删除(设置标志'已删除')
PrivateMessages的主页应如下所示:
E.g。 User1将Message1发送给User2和User3。 在私人消息页面上,我必须显示2条相同的消息:
下一步 - User2回复Message2,我将在同一页面上看到:
下一步,我回复message3,我会看到
等等。
任何人都可以提供表结构吗? 我正在使用MySQL 5.5
主要问题。如何只获取每个对话框的最后一条未删除消息?
UPD。
我需要在当前用户和其他用户之间的主页对话框列表中看到(具有分页,按日期DESC排序)。
答案 0 :(得分:10)
我将首先回答您的主要问题,然后显示我将用于此的表格结构。
仅获取特定对话框的最后一条未删除消息:
select
Message.Id
,Message.Subject
,Message.Content
from Message
join Junc_Message_To on Fk_Message = Message.Id
where Junc_Message_To.Fk_User = {RECIPIENT_ID}
and Message.Fk_User__From = {SENDER_ID}
and Junc_Message_To.Deleted is null
order by Junc_Message_To.Sent desc
limit 1
可以使用简单的三表结构。
表1存储用户记录 - 每个用户一条记录。
表2存储了消息记录 - 每条消息一条记录,外键与发送消息的用户有关。
表3列出了消息和发送消息的用户之间的关联。
以下是用于创建上表图表的SQL:
create table `User` (
`Id` int not null auto_increment ,
`Username` varchar(32) not null ,
`Password` varchar(32) not null ,
primary key (`Id`) ,
unique index `Username_UNIQUE` (`Username` ASC) )
engine = InnoDB
create table `Message` (
`Id` int not null auto_increment ,
`Fk_User__From` int not null ,
`Subject` varchar(256) not null ,
`Content` text not null ,
primary key (`Id`) ,
index `Fk_Message_User__From` (`Fk_User__From` ASC) ,
constraint `Fk_Message_User__From`
foreign key (`Fk_User__From` )
references `User` (`Id` )
on delete cascade
on update cascade)
engine = InnoDB
create table `Junc_Message_To` (
`Fk_Message` int not null ,
`Fk_User` int not null ,
`Sent` datetime not null ,
`Read` datetime not null ,
`Deleted` datetime not null ,
PRIMARY KEY (`Fk_Message`, `Fk_User`) ,
INDEX `Fk_Junc_Message_To__Message` (`Fk_Message` ASC) ,
INDEX `Fk_Junc_Message_To__User` (`Fk_User` ASC) ,
constraint `Fk_Junc_Message_To__Message`
foreign key (`Fk_Message` )
references `Message` (`Id` )
on delete cascade
on update cascade,
constraint `Fk_Junc_Message_To__User`
foreign key (`Fk_User` )
references `User` (`Id` )
on delete cascade
on update cascade)
engine = InnoDB
答案 1 :(得分:4)
我过去使用MessageRecipient表完成此操作,该表只包含MessageID,ReceiverID和Status。我也在该表中有FolderID,但是你没有这个要求。消息表根本不存储有关收件人的任何信息。
这是一个检索用户邮件的联接,但可以防止收件人之间邮件主题和正文的重复。
答案 2 :(得分:4)
根据您提供的信息,这是我的方法。
用户表格是给定的。我只是id
和name
。
我们显然需要一个表来存储消息。我们需要知道谁是author
,subject
,message
内容,以及(可能)created
/发送的时间。
我们需要知道message_recipients
是谁。从技术上讲,即使message.author
也会发送message
的副本(在大多数情况下),但通常会将其放在folder='Sent'
中。其他人都可能在folder="Inbox"
中得到它。然后,用户可以将message
移动到他们的folder='Trash'
或完全删除它。如果由于某种原因您需要在用户删除邮件后保留邮件,则可以通过folder='Deleted'
创建folder.type='System'
来完成此操作。如果没有,只需删除message_recipients
表中message_recipient.user
的记录。
所以这是相关的信息。请参阅模式和数据后查询的测试用例。
<强>架构:强>
SET FOREIGN_KEY_CHECKS=0;
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` tinytext NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
CREATE TABLE `message` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`author` int(11) unsigned NOT NULL,
`subject` varchar(255) NOT NULL,
`message` mediumtext NOT NULL,
`created` datetime NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_m_author` (`author`),
CONSTRAINT `fk_m_author` FOREIGN KEY (`author`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `message_folder_type`;
CREATE TABLE `message_folder_type` (
`name` varchar(40) NOT NULL,
`type` enum('System','User') NOT NULL DEFAULT 'User',
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `message_recipient`;
CREATE TABLE `message_recipient` (
`message` int(11) unsigned NOT NULL,
`user` int(11) unsigned NOT NULL,
`folder` varchar(40) NOT NULL,
PRIMARY KEY (`message`,`user`),
KEY `fk_mr_user` (`user`),
KEY `fk_mr_message_folder` (`folder`),
CONSTRAINT `fk_mr_message_folder` FOREIGN KEY (`folder`) REFERENCES `message_folder_type` (`name`) ON UPDATE CASCADE,
CONSTRAINT `fk_mr_message` FOREIGN KEY (`message`) REFERENCES `message` (`id`) ON UPDATE CASCADE,
CONSTRAINT `fk_mr_user` FOREIGN KEY (`user`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
测试数据:
INSERT INTO `user` VALUES ('1', 'Bob');
INSERT INTO `user` VALUES ('2', 'Harry');
INSERT INTO `user` VALUES ('3', 'Salley');
INSERT INTO `user` VALUES ('4', 'Jim');
INSERT INTO `user` VALUES ('5', 'Jake');
INSERT INTO `user` VALUES ('6', 'Randall');
INSERT INTO `user` VALUES ('7', 'Ashley');
INSERT INTO `message` VALUES ('1', '4', 'Message 1', 'this is a message', '2011-03-01 15:47:07');
INSERT INTO `message` VALUES ('2', '2', 'Message 2', 'this is a reply to message 1', '2011-03-02 15:47:28');
INSERT INTO `message` VALUES ('3', '7', 'Message 3', 'another cool message', '2011-03-02 15:48:15');
INSERT INTO `message` VALUES ('4', '4', 'Message 4', 'blah blah blah Sally', '2011-03-09 15:48:43');
INSERT INTO `message_folder_type` VALUES ('Deleted', 'System');
INSERT INTO `message_folder_type` VALUES ('Inbox', 'User');
INSERT INTO `message_folder_type` VALUES ('Sent', 'User');
INSERT INTO `message_folder_type` VALUES ('Trash', 'User');
INSERT INTO `message_recipient` VALUES ('1', '1', 'Inbox');
INSERT INTO `message_recipient` VALUES ('1', '2', 'Inbox');
INSERT INTO `message_recipient` VALUES ('2', '4', 'Inbox');
INSERT INTO `message_recipient` VALUES ('2', '5', 'Inbox');
INSERT INTO `message_recipient` VALUES ('3', '5', 'Inbox');
INSERT INTO `message_recipient` VALUES ('1', '4', 'Sent');
INSERT INTO `message_recipient` VALUES ('2', '2', 'Sent');
INSERT INTO `message_recipient` VALUES ('3', '7', 'Sent');
INSERT INTO `message_recipient` VALUES ('4', '4', 'Sent');
INSERT INTO `message_recipient` VALUES ('1', '3', 'Trash');
INSERT INTO `message_recipient` VALUES ('4', '3', 'Trash');
测试用例: 获取每个对话框的最后一条未删除消息
我不完全确定这意味着什么,但我会假设“在给定用户的收件箱中”和“不在系统已删除文件夹中”作为我查询的一部分。
SELECT message.`subject`, message.message, message.`author`
FROM message_recipient
INNER JOIN message ON message.id = message_recipient.message
WHERE
message_recipient.user = 4
AND message_recipient.folder != 'Deleted'
ORDER BY message.created DESC
根据提供的测试数据,这给出了以下结果:
Subject Message Author
Message 4 blah blah blah Sally 4
Message 2 this is a reply to message 1 2
Message 1 this is a message 4
答案 3 :(得分:1)
如果我是DB的架构师,我会制作这样的结构(约)
CREATE TABLE statuses(
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
description VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (id),
UNIQUE INDEX name (name)
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
CREATE TABLE users(
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX name (name)
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
CREATE TABLE messages(
id INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
reply_to INT(11) UNSIGNED NOT NULL,
sender INT(11) UNSIGNED NOT NULL,
recipient INT(11) UNSIGNED NOT NULL,
subject VARCHAR(255) DEFAULT NULL,
message TEXT DEFAULT NULL,
`time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
INDEX FK_messages_messages_id (reply_to),
INDEX FK_messages_users_id_recipient (recipient),
INDEX FK_messages_users_id_sender (sender),
CONSTRAINT FK_messages_messages_id FOREIGN KEY (reply_to)
REFERENCES messages (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FK_messages_users_id_recipient FOREIGN KEY (recipient)
REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT FK_messages_users_id_sender FOREIGN KEY (sender)
REFERENCES users (id) ON DELETE NO ACTION ON UPDATE NO ACTION
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
CREATE TABLE messages_statuses(
message_id INT(11) UNSIGNED NOT NULL,
status_id INT(11) UNSIGNED NOT NULL,
PRIMARY KEY (message_id, status_id),
INDEX FK_messages_statuses_statuses_id (status_id),
CONSTRAINT FK_messages_statuses_messages_id FOREIGN KEY (message_id)
REFERENCES messages (id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FK_messages_statuses_statuses_id FOREIGN KEY (status_id)
REFERENCES statuses (id) ON DELETE CASCADE ON UPDATE CASCADE
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
我在这里看不到任何困难,但如果你有任何疑问 - 请随时提出。
答案 4 :(得分:0)
id* INT, sender_id INT, recipient_id INT, message TEXT,
flag_s_deleted = 0 TINYINT, flag_r_deleted = 0 TINYINT, flag_r_read = 0 TINYINT,
sent_datetime DATETIME
“我怎么才能得到最后一个 每个对话框的未删除消息?“
你在这里:
select * from (...) where
(sender_id = ID1 and recipient_id = ID2 and flag_s_deleted = 0)
or (sender_id = ID2 and recipient_id = ID1 and flag_r_deleted = 0)
order by sent_date desc LIMIT 1
您(ID1)与其他人(ID2)之间的最后一条消息
答案 5 :(得分:-1)
create database testMessage
go
use testMessage
go
CREATE TABLE [user] (
userid int NOT NULL IDENTITY,
name nvarchar(200) NOT NULL,
PRIMARY KEY (userid)
)
go
CREATE TABLE [message] (
msg_id int NOT NULL IDENTITY,
userid int NOT NULL,
msgContent nvarchar(200) NOT NULL,
created datetime NOT NULL default getdate(),
PRIMARY KEY (msg_id)
)
go
ALTER TABLE [message]
ADD FOREIGN KEY (userid) REFERENCES [user](userid)
ON DELETE CASCADE
ON UPDATE CASCADE
go
CREATE TABLE message_folder_type (
message_folder_type_name varchar(40) NOT NULL,
[type] varchar(10) NOT NULL DEFAULT 'User',
PRIMARY KEY (message_folder_type_name)
)
go
CREATE TABLE message_recipient (
message_recipient int NOT NULL,
userid int NOT NULL,
message_folder_type_name varchar(40) NOT NULL,
PRIMARY KEY (message_recipient,userid)
)
go
ALTER TABLE message_recipient
ADD FOREIGN KEY (message_folder_type_name) REFERENCES message_folder_type(message_folder_type_name)
ON DELETE CASCADE
ON UPDATE CASCADE
ALTER TABLE message_recipient
ADD FOREIGN KEY (message_recipient) REFERENCES [message](msg_id)
ON DELETE CASCADE
ON UPDATE CASCADE
ALTER TABLE message_recipient
ADD FOREIGN KEY (userid) REFERENCES [user](userid)
INSERT INTO [user] VALUES ('Bob');
INSERT INTO [user] VALUES ('Harry');
INSERT INTO [user] VALUES ('Salley');
INSERT INTO [user] VALUES ('Jim');
INSERT INTO [user] VALUES ('Jake');
INSERT INTO [user] VALUES ('Randall');
INSERT INTO [user] VALUES ('Ashley');
INSERT INTO [message] VALUES ('4', 'this is a message', '2011-03-01 15:47:07');
INSERT INTO [message] VALUES ('2', 'this is a reply to message 1', '2011-03-02 15:47:28');
INSERT INTO [message] VALUES ('7', 'another cool message', '2011-03-02 15:48:15');
INSERT INTO [message] VALUES ('4', 'blah blah blah Sally', '2011-03-09 15:48:43');
INSERT INTO message_folder_type VALUES ('Deleted', 'System');
INSERT INTO message_folder_type VALUES ('Inbox', 'User');
INSERT INTO message_folder_type VALUES ('Sent', 'User');
INSERT INTO message_folder_type VALUES ('Trash', 'User');
INSERT INTO message_recipient VALUES ('1', '1', 'Inbox');
INSERT INTO message_recipient VALUES ('1', '2', 'Inbox');
INSERT INTO message_recipient VALUES ('2', '4', 'Inbox');
INSERT INTO message_recipient VALUES ('2', '5', 'Inbox');
INSERT INTO message_recipient VALUES ('3', '5', 'Inbox');
INSERT INTO message_recipient VALUES ('1', '4', 'Sent');
INSERT INTO message_recipient VALUES ('2', '2', 'Sent');
INSERT INTO message_recipient VALUES ('3', '7', 'Sent');
INSERT INTO message_recipient VALUES ('4', '4', 'Sent');
INSERT INTO message_recipient VALUES ('1', '3', 'Trash');
INSERT INTO message_recipient VALUES ('4', '3', 'Trash');
SELECT [message].msg_id, [message].msgContent
FROM message_recipient
INNER JOIN message ON [message].msg_id = message_recipient.message_recipient
WHERE
message_recipient.userid = 4
AND message_recipient.message_folder_type_name != 'Deleted'
ORDER BY message.created DESC
fast action for sqlserver