SQL小提琴
http://sqlfiddle.com/#!2/1c5fc3/1
我正在尝试创建简单的邮件系统,但我遇到了SQL查询所需结果的问题。 这是我的桌子;我想获取INBOX数据..
INBOX Definiton解决了这个问题:
这应该是收件箱中的线程显示,即。谷歌邮件,但只显示该线程中的最后一条消息与原始创建线程的用户和最后一个在线程中回复的用户,如果最后一个用户是创建该线程的同一用户,并且beetween中没有回复消息不会在收件箱中显示出来。
TABLES:
THREAD
id_thread
id_last_message
id_user_inital
id_user_last
THREAD_USERS
id
id_thread
id_user
THREAD_MESSAGES
id_thread_messages
id_user_sender
id_thread
datetime
subject
body
MESSAGE_STATUS
id_messsage_status
id_thread_messages
id_user
status
datetime
我的逻辑是: 一旦发送了消息
THREAD
id_thread id_last_message id_user_inital id_user_last
1 1 1 1
THREAD_USERS
id id_thread id_user
1 1 1
2 1 2
THEREAD_MESSAGES
id_thread_messages id_user_sender id_thread datetime subject body
1 1 1 07.09.2014 16:02 'title' 'text message'
MESSAGE_STATUS
id_message_status id_thread_messages id_user status datetime
1 1 1 4 07.09.2014 16:02
2 1 2 1 07.09.2014 16:02
让我们说状态可以是
0 = deleted (do not show at all)
1 = new (show only to user that is on the receiving end)
2 = read (this status will be shown to all users in the thread)
3 = replied (show only to user that makes this action)
4 = sent (show only to user that makes this action)
查询:
SELECT *
FROM thread
JOIN thread_users
ON thread.id_thread = thread_users.id_thread
JOIN thread_messages
ON thread.id_thread = thread_messages.id_thread
JOIN message_status
ON thread_messages.id_thread_messages = message_status.id_thread_messages
WHERE
thread_users.id_user = 2
AND message_status.status != 0
AND message_status.status != 4
AND thread.id_user_last != message_status.id_user
示例数据
主题
id_thread id_last_message id_user_inital id_user_last
1 4 1 2
2 2 3 3
3 3 4 4
THREAD_USERS
id id_thread id_user
1 1 1
2 1 2
3 2 3
4 2 2
5 3 4
6 3 2
THEREAD_MESSAGES
id_thread_messages id_user_sender id_thread datetime subject body
1 1 1 07.09.2014 16:02 'title' 'text message'
2 3 2 07.09.2014 16:05 'hey two' 'foo'
3 4 2 07.09.2014 16:07 'hey two' 'bar'
4 2 1 07.09.2014 16:10 'title' 'replay on 1st'
MESSAGE_STATUS
id_message_status id_thread_messages id_user status datetime
1 1 1 4 07.09.2014 16:02
2 1 2 1 07.09.2014 16:02
3 2 3 4 07.09.2014 16:05
4 2 2 1 07.09.2014 16:05
5 3 4 4 07.09.2014 16:07
6 3 2 1 07.09.2014 16:07
7 4 2 4 07.09.2014 16:10
8 4 1 1 07.09.2014 16:10
你如何从这种情况中提取INBOX数据,因为我在圈子里旋转几个小时并且不能完全弄清楚我做错了什么。
谢谢。
答案 0 :(得分:1)
我认为这是您正在寻找的解决方案
SELECT * FROM thread
JOIN thread_users ON thread.id_thread = thread_users.id_thread
JOIN thread_messages ON thread.id_thread = thread_messages.id_thread
JOIN message_status ON thread_messages.id_thread_messages = message_status.id_thread_messages
WHERE thread_users.id_user = 2
AND thread_users.id_user = message_status.id_user
AND message_status.status != 0
AND message_status.status != 4
AND thread.id_user_last != message_status.id_user
答案 1 :(得分:1)
考虑到消息状态的说明后更新了解决方案:
SELECT DISTINCT t.*, tm.* , ms.*
FROM thread t
-- tm should be last message
INNER JOIN thread_messages tm ON t.id_thread = tm.id_thread
INNER JOIN message_status ms ON (ms.id_thread_messages = tm.id_thread_messages)AND
(ms.id_user=2)AND
(ms.status!=0)
-- try to find message after tm, and then in WHERE filter only those cases where there is no message after tm
LEFT JOIN thread_messages tm_next
INNER JOIN message_status ms_next ON (ms_next.id_thread_messages = tm_next.id_thread_messages)AND
(ms_next.id_user=2)AND
(ms_next.status!=0)
ON (t.id_thread = tm_next.id_thread)and
(tm_next.datetime>tm.datetime)
LEFT JOIN thread_messages tm_other
INNER JOIN message_status ms_other ON (ms_other.id_thread_messages = tm_other.id_thread_messages)AND
(ms_other.id_user=2)AND
(ms_other.status!=0)
ON (t.id_thread = tm_other.id_thread)and
(tm_other.id_thread_messages!=tm.id_thread_messages)and
(tm_other.id_user_sender!=2)
WHERE
-- ensure tm is last message in thread
(tm_next.id_thread is null)and
(
-- there is a non deleted message from another user in current thread
(tm_other.id_thread_messages is not null)or
-- last message is not from current user
(tm.id_user_sender!=2)
)
SqlFiddle是here。 让我知道这对你有用。
答案 2 :(得分:0)
现在有了INBOX的含义的描述,我建议你在查询中严重依赖EXISTS子句。以下是它的外观示例:
SELECT *
FROM thread t INNER JOIN
thread_messages tm ON t.id_thread = tm.id_thread
WHERE
EXISTS ( -- User is in the thread.
SELECT * FROM thread_users tu
WHERE t.id_thread = tu.id_thread AND tu.id_user = 2
)
AND NOT EXISTS ( -- Exclude earlier messages for thread.
SELECT * FROM thread_messages WHERE
tm.id_thread = id_thread AND datetime > tm.datetime
AND EXISTS (-- Exclude deleted messages here
SELECT * FROM message_status
WHERE thread_messages.id_thread_messages = id_thread_messages
AND status != 0
AND status != 4
)
)
AND EXISTS ( -- Include messages that were not deleted or send to self.
SELECT * FROM message_status
WHERE tm.id_thread_messages = id_thread_messages
AND status != 0
AND status != 4
AND t.id_user_last != id_user -- not sure what is this for
)
AND EXISTS ( -- Include threads with messages from several users
SELECT * FROM thread_messages
WHERE tm.id_thread = id_thread
AND tm.id_user_sender != t.id_user_inital)