【问题标题】:How to get the last message in a thread SQL Query如何获取线程 SQL Query 中的最后一条消息
【发布时间】:2019-06-14 00:17:22
【问题描述】:

我有两张桌子,listhdthreadslisthdmessageslisthdthreads 是父表,每个线程中都有消息作为子表。

CREATE TABLE `listhdthreads` (
  `idx` int(11) NOT NULL AUTO_INCREMENT,
  `fromUser` int(11) NOT NULL,
  `respondingUser` int(11) DEFAULT NULL,
  `attachments` varchar(300) DEFAULT NULL,
  `customerId` int(11) NOT NULL,
  `locationId` int(11) DEFAULT NULL,
  `areaId` int(11) DEFAULT NULL,
  `assetId` int(11) DEFAULT NULL,
  `projectId` int(11) DEFAULT NULL,
  `contactId` int(11) DEFAULT NULL,
  `title` int(11) NOT NULL,
  `priority` int(11) NOT NULL,
  `status` int(11) NOT NULL,
  `createdAt` datetime NOT NULL,
  `ddGroup` int(1) DEFAULT NULL,
  PRIMARY KEY (`idx`)
)

CREATE TABLE `listhdmessages` (
  `idx` int(11) NOT NULL AUTO_INCREMENT,
  `parentThreadId` int(11) NOT NULL,
  `createdAt` datetime NOT NULL,
  `sendingUser` int(11) NOT NULL,
  `text` varchar(300) NOT NULL,
  `adminMessage` bit(1) DEFAULT b'0',
  `updatedAt` datetime DEFAULT NULL,
  PRIMARY KEY (`idx`),
  KEY `parentId` (`parentThreadId`),
  CONSTRAINT `listhdmessages_ibfk_1` FOREIGN KEY (`parentThreadId`) REFERENCES `listhdthreads` (`idx`) ON DELETE CASCADE ON UPDATE CASCADE
)

现在我有这个当前查询,它用所有线程填充一个表,我想包括最后一次发送消息(我已经有了),以及最后一条消息本身的内容(这是我需要的帮助)。

当前的查询是这样的(删除了不必要的列)

SELECT MAX(m.createdAt) as latestMessage,
FROM listhdthreads as hd 
LEFT JOIN listhdmessages m ON hd.idx = m.parentThreadId 
LEFT JOIN listcustomers c ON hd.customerId = c.idx 
LEFT JOIN listlocations l ON hd.locationId = l.idx 
LEFT JOIN listprojects lp ON hd.projectId = lp.idx
LEFT JOIN listusers lu ON hd.contactId = lu.idx 
LEFT JOIN listusers lus ON hd.fromUser = lus.idx 
LEFT JOIN listusers lusu ON hd.respondingUser = lusu.idx
LEFT JOIN deschdtitles t ON hd.title = t.idx 
LEFT JOIN deschdpriorities p ON hd.priority = p.idx 
LEFT JOIN deschdstatus s ON hd.status = s.idx 
LEFT JOIN helpmessageparticipants hmp ON hd.idx = hmp.parentThreadId
GROUP BY hd.idx

我在尝试获取最新消息本身时不知所措。我该怎么办?我正在使用 MySQL 5.6。

编辑:抱歉,我忘记包含其余查询正常工作所必需的组。这就是让我头疼的原因。

编辑 2:想通了。将我的初始查询变成了一个子查询,我只是按照这样一种方式排序,即每个线程的第一行正是我想要的,然后在它之外进行分组。

SELECT * FROM
(SELECT hd.idx, hd.ddGroup, c.name as customer, IF(hd.locationId=-1,"None",l.name) as location, CONCAT(lu.firstname, ' ', lu.lastname) as contactId, t.title, lp.number, 
UPPER(CONCAT(SUBSTRING(lus.firstname,1,1), SUBSTRING(lus.lastname,1,1))) as createdBy, IF(hd.respondingUser=-1,"---",UPPER(CONCAT(SUBSTRING(lusu.firstname,1,1), SUBSTRING(lusu.lastname,1,1)))) as forUser,
p.priority,s.status,hd.customerId,hd.locationId,hd.areaId,hd.assetId,hd.projectId,
m.createdAt as latestMessage, m.text as LastMessage
FROM listhdthreads as hd 
LEFT JOIN listhdmessages m ON hd.idx = m.parentThreadId 
LEFT JOIN listcustomers c ON hd.customerId = c.idx 
LEFT JOIN listlocations l ON hd.locationId = l.idx 
LEFT JOIN listprojects lp ON hd.projectId = lp.idx
LEFT JOIN listusers lu ON hd.contactId = lu.idx 
LEFT JOIN listusers lus ON hd.fromUser = lus.idx 
LEFT JOIN listusers lusu ON hd.respondingUser = lusu.idx
LEFT JOIN deschdtitles t ON hd.title = t.idx 
LEFT JOIN deschdpriorities p ON hd.priority = p.idx 
LEFT JOIN deschdstatus s ON hd.status = s.idx 
LEFT JOIN helpmessageparticipants hmp ON hd.idx = hmp.parentThreadId
ORDER BY hd.idx, m.createdAt DESC) as t
GROUP BY t.idx

【问题讨论】:

  • select * from .... order by m.createdAt desc limit 1
  • 我忘记了在查询的末尾我有一个 GROUP BY hd.idx 这使它有点复杂。
  • 能否添加示例数据和预期输出?如果可能的话,请添加sqlfiddle.comfiddle
  • sqlfiddle.com/#!9/c417d 这只是消息的单线程。我想要的输出是线程 idx、最新消息的时间戳和消息内容本身。我删除了所有其他表,因为它们不是必需的。所以输出将是 idx 100004, createdAt 2019-05-28 15:52:39, text 'Perfect.谢谢'

标签: mysql sql


【解决方案1】:

您可以在 ON 子句中使用相关子查询。在子查询中,您会从线程中获取最后 (MAX) 条消息。

SELECT hd.*, m.* -- select columns you need
FROM listhdthreads as hd 
LEFT JOIN listhdmessages m ON m.idx = (
    SELECT MAX(mmax.idx)
    FROM listhdmessages mmax
    WHERE mmax.parentThreadId = hd.idx
)
-- JOIN more tables

使用 AUTO_INCREMENT 列比使用createdAt 更好更简单。 createdAt 不是唯一的,同一线程的两条消息可以在同一秒发布,这一事实就足够了。

【讨论】:

    【解决方案2】:
    SELECT m.createdAt as latestMessage
    FROM listhdthreads as hd
    LEFT JOIN listhdmessages m ON hd.idx = m.parentThreadId
    ...
    GROUP BY m.parentThreadId
    ORDER BY m.createdAt DESC LIMIT 1
    
    

    SELECT hd.idx, m.createdAt as latestMessage
    FROM listhdthreads as hd
    LEFT JOIN listhdmessages m ON hd.idx = m.parentThreadId
    ...
    GROUP BY hd.idx, m.createdAt
    ORDER BY m.createdAt DESC LIMIT 1
    

    【讨论】:

    • 我忘了在查询末尾包含GROUP BY hd.idx,这使它有点复杂。我想我需要一个子查询?不确定。
    • 据此我不知道要按哪些列分组...如果您需要GROUP BY hd.idx,那么您需要选择已分组的列
    • 其他联接供其他实体包括在内。这就像一个消息系统,关于我们与之交互的客户和供应商的整个层次结构以及制作消息的人的用户名,但是老实说,您可以忽略它们,因为它们本质上都是可选的。
    • @bjk116 我对答案进行了一些编辑,您可以尝试一下
    • 这仅返回最新的线程,但它确实包含所述线程的最后一条消息,因此很有希望。不知何故需要调整它。
    猜你喜欢
    • 2019-12-26
    • 2015-09-17
    • 2018-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-24
    • 2016-10-12
    相关资源
    最近更新 更多