質問

プライベートメッセージでユーザー間でダイアログを保存するのに最適なテーブル構造は何ですか?各ユーザーは、多くのレセピエントに個人的なメッセージを送信できます。各メッセージには送信者のフラグがあります:メッセージが削除されているかどうかは、各メッセージが受信機のフラグを持っています:メッセージが未読、読み取り、または削除されます各メッセージは削除できます(flag '削除'を設定します)

privatemessagesのメインページは次のようになります。

例:user1はmessage1をuser2とuser3に送信します。プライベートメッセージページに、2つの同じメッセージを表示する必要があります。

  1. message1をuser2に送信しました
  2. message1をuser3に送信しました

次のステップ-user2はmessage2に返信します。同じページで次のように表示されます。

  1. user2からmessage2を受信しました(message1の返信)
  2. message1をuser3に送信しました

次のステップでは、message3に答えます。

  1. message3をuser2に送信しました
  2. message1をuser3に送信しました

等々。

誰でもテーブル構造を提供できますか? MySQL 5.5を使用しています

主な質問。各ダイアログの最後の非削除されていないメッセージのみを取得するにはどうすればよいですか?

upd。

現在のユーザーと他のユーザーの間で、メインページダイアログリストで(ページネーションを使用して、DATE DESCでソートされた)を確認する必要があります。

役に立ちましたか?

解決

最初にあなたの主な質問に答えてから、これに使用するテーブル構造を示します。

特定のダイアログの最後の非削除されていないメッセージのみを取得するには:

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

単純な3つのテーブル構造を使用できます。

表1には、ユーザーレコード - ユーザーごとに1つのレコードがあります。

表2はメッセージレコードを保存します - メッセージごとに1つのレコード、外部キーはメッセージを送信したユーザーに関連しています。

表3には、メッセージとメッセージが送信されたユーザーとの相関関係を保存します。

enter image description here

上記の表図を作成するために使用される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

他のヒント

私はこれを過去に、メッセージ、ReceiverID、およびステータスを単純に含むMessagerecipientテーブルでこれを行いました。そのテーブルにもFolderIDがありましたが、その要件はありません。メッセージテーブルは、受信者に関する情報をまったく保存しませんでした。

ユーザーメッセージを取得するための結合ですが、受信者間のメッセージサブジェクトとボディの重複を防ぎます。

これがあなたが提供した情報に基づいて、これに対する私のアプローチです。

ユーザーテーブルはギブインです。私のものはただ idname.

メッセージを保存するためのテーブルが明らかに必要です。誰を知る必要があります authored it、 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

私が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;

ここでは何も見えませんが、質問があれば、お気軽にお問い合わせください。

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)の間の最後のメッセージ

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
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top