我正在尝试为邮件系统制定SQL查询,该查询将返回状态为“OPEN”且其最后一条消息未被某个组中的用户发布的所有线程的列表。
查询中涉及的表是:
threads
-------
threadId
timestamp
subject
status
clientId
messages
--------
messageId
userId
messagebody
timestamp
threadId
users
-----
userId
username
groupId
当前查询是:
SELECT threadId, timestamp, subject, status, clientId
FROM threads
WHERE status='OPEN'
ORDER BY timestamp DESC
工作正常;但我现在有一个新的要求 - 如果线程中的最后一条消息是由groupId
为1的用户发布的,那么它不应该在结果集中。
包括我需要的信息很简单:
SELECT threadId, timestamp, subject, status, clientId
FROM threads
INNER JOIN messages USING(threadId)
INNER JOIN users USING(userId)
WHERE status='OPEN'
GROUP BY threadId
ORDER BY timestamp DESC
但此时我陷入困境,因为我无法弄清楚如何根据特定组中messages.userId
timestamp
的{{1}}来筛选线程。我已经查看了HAVING
以及所有聚合函数,似乎没有任何内容符合要求。
修改
我可能不够清楚,所以我将尝试用一个例子说明。
以下是一些示例数据:
线程
threadId | timestamp | subject | status | clientId
--------------------------------------------------
1 | 1 | One | OPEN | 1
2 | 10 | Two | OPEN | 4
3 | 26 | Three | OPEN | 19
4 | 198 | Four | OPEN | 100
讯息
messageId | userId | messagebody | timestamp | threadId
-------------------------------------------------------
1 | 3 | Hello, World| 1 | 1
2 | 1 | Hello | 3 | 1
3 | 1 | ^&%&6 | 10 | 2
4 | 2 | Test | 12 | 2
5 | 4 | Hi mum | 26 | 3
6 | 1 | More tests | 100 | 4
用户
userId | username | groupId
---------------------------
1 | Gareth | 1
2 | JimBob | 2
3 | BillyBob | 2
4 | Bod | 3
在此示例中,数据集线程1和4应该从查询中删除,因为用户Gareth
(组1的成员)是最后一个发布给它们的(threadId 1中的messageId 2和messageId 5 in threadId 4)。因此,结果集应该只包含线程2和3的线程数据(threadId,timestamp,subject,status和clientId)。
我为此测试数据创建了SQLfiddle。
有人能指出我在正确的方向吗?
答案 0 :(得分:2)
听起来你想要这个:
SELECT threadId, timestamp, subject, status, clientId
FROM threads t
INNER JOIN messages m
ON t.threadId = m.threadId
INNER JOIN users u
ON m.userId = u.userId
and u.groupId != 1 --placed the groupId filter here.
WHERE status='OPEN'
GROUP BY threadId
ORDER BY timestamp DESC
编辑,这似乎可以满足您的需求:
SELECT t.threadId,
t.timestamp,
t.subject,
t.status,
t.clientId
FROM threads t
INNER JOIN messages m
ON t.threadId = m.threadId
INNER JOIN users u
ON m.userId = u.userId
WHERE status='OPEN'
AND NOT EXISTS (select t1.threadid
FROM threads t1
INNER JOIN messages m
ON t1.threadId = m.threadId
INNER JOIN users u
ON m.userId = u.userId
where u.groupid = 1
and t.threadid = t1.threadid)
ORDER BY timestamp DESC
答案 1 :(得分:1)
在查询中添加 LIMIT 1
是否可以解决您的问题?
SELECT threadId, timestamp, subject, status, clientId
FROM threads
INNER JOIN messages USING(threadId)
INNER JOIN users USING(userId)
WHERE status='OPEN'
GROUP BY threadId
ORDER BY timestamp DESC
LIMIT 1
或将where子句更改为
WHERE status='OPEN' and groupID<>1
击> <击> 撞击>
我认为这就是你想要的?
select * from threads
where threadId not in
(
select messages.threadId
from messages
inner join (select threadId, MAX(timestamp) maxtime from messages group by threadId) t
on messages.threadId = t.threadId
and messages.timestamp = t.maxtime
where messages.userId=1
)