1

我有 SQL 语句

SELECT * 
FROM `assocMessages`
LEFT JOIN `messageThreads` ON `messageThreads`.`threadID` = `assocMessages`.`threadID` 
LEFT JOIN `messages` ON `messageThreads`.`threadID` = `messages`.`threadID` 
WHERE `assocMessages`.`accountID` =1
GROUP BY `messageThreads`.`threadID` 
ORDER BY `messages`.`messageSent` DESC

它旨在获取message threads与当前用户相关联的列表。它还旨在获取message与 found 相关联的最新message threads消息,但是,它仅显示在 found 上发送的第一条消息message thread。我添加了 statement ORDER BY messages.messageSent DESC,但是,无论它在那里,或者方向是ASCor DESC,它只显示第一个message发送。有谁知道我能做什么?我试图将其保留在单个 SQL 语句中,以防止遇到 n+1 选择问题。

编辑

我刚刚尝试反转表格,所以它最初有FROM messages并且assocMessages表格稍后加入

编辑

关联消息:

+-----------+----------+
| accountID | threadID |
+-----------+----------+
| 1         | 1        |
+-----------+----------+
| 2         | 1        |
+-----------+----------+

消息线程:

+----------+---------------------+
| threadID | threadCreatedOn     |
+----------+---------------------+
| 1        | 2013-05-01 12:00:00 |
+----------+---------------------+

留言:

+-----------+----------+-----------+-------------+---------------------+
| messageID | threadID | accountID | messageBody | messageSent         |
+-----------+----------+-----------+-------------+---------------------+
| 1         | 1        | 1         | First Hi    | 2013-05-01 12:00:00 |
+-----------+----------+-----------+-------------+---------------------+
| 2         | 1        | 2         | Second Hi   | 2013-05-01 12:01:00 |
+-----------+----------+-----------+-------------+---------------------+

因此,当被查询时,它将返回一个线程列表(accountID1 已注册),其中最近的 2message是2messageID发送的accountID

返回的内容:

+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| accountID | threadID | threadCreated       | messageID | messageBody | messageSent         | threadID | accountID |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| 1         | 1        | 2013-05-01 12:00:00 | 1         | First Hi    | 2013-05-01 12:00:00 | 1        | 1         |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+

应该返回什么:

+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| accountID | threadID | threadCreated       | messageID | messageBody | messageSent         | threadID | accountID |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| 1         | 1        | 2013-05-01 12:00:00 | 2         | Second Hi   | 2013-05-01 12:01:00 | 1        | 2         |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+

如果我删除返回什么group by

+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| accountID | threadID | threadCreated       | messageID | messageBody | messageSent         | threadID | accountID |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| 1         | 1        | 2013-05-01 12:00:00 | 2         | Second Hi   | 2013-05-01 12:01:00 | 1        | 2         |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+
| 1         | 1        | 2013-05-01 12:00:00 | 1         | First Hi    | 2013-05-01 12:00:00 | 1        | 1         |
+-----------+----------+---------------------+-----------+-------------+---------------------+----------+-----------+

第一个accountIDs 是相同的,因为它们是从messageThreads关联返回的

最终编辑(暂时)

当我删除 时GROUP BY messageThreads.threadID,它会显示每个线程中的所有消息

4

2 回答 2

1

我认为您的部分问题是 MySQL 应用GROUP BY. MySQL扩展了 GROUP BY 函数,允许从聚合函数和 GROUP BY 中排除选择列表中的项目。此扩展可能会导致意外结果。

我认为以下内容将为您提供所需的结果:

SELECT a.accountId,
  a.threadId,
  mt.threadCreatedOn,
  m.messageId,
  m.messageBody,
  m.messageSent,
  m.accountId messageAccountId
FROM `assocMessages` a
INNER JOIN `messageThreads` mt
  ON mt.`threadID` = a.`threadID` 
LEFT JOIN
(
  select m1.*
  from messages m1
  inner join
  (
    select max(messageSent) messageSent,
      threadId
    from messages
    group by threadid
  ) m2
    on m1.threadid = m2.threadid
    and m1.messageSent = m2.messageSent
) m
  ON mt.`threadID` = m.`threadID` 
WHERE a.`accountID` =1
ORDER BY m.`messageSent` DESC;

请参阅带有演示的 SQL Fiddle

于 2013-05-01T17:27:05.420 回答
0

我对您的实际要求感到有些困惑,但是请看一下:

SELECT `assocMessages`.*, `messageThreads`.`threadCreatedOn`, `messages`.`messageBody`, `messages`.`messageSent` 
FROM `assocMessages`
LEFT JOIN `messageThreads` ON `messageThreads`.`threadID` = `assocMessages`.`threadID`
LEFT JOIN `messages` ON `messageThreads`.`threadID` = `messages`.`threadID` AND `assocMessages`.`accountID`=`messages`.`accountID`
WHERE `assocMessages`.`accountID` =1
ORDER BY `messages`.`messageSent` DESC

这是你想要做的吗?我修改了消息

messageID   threadID    accountID   messageBody     messageSent
1           1           1           First Hi    2013-05-01 12:00:00
2           1           2           Second Hi   2013-05-01 12:01:00
3           1           1           Third Message   2013-05-01 12:02:00

SQL查询结果为:

accountID   threadID    threadCreatedOn     messageBody     messageSent
1           1           2013-05-01 12:00:00     Third Message   2013-05-01 12:02:00
1           1           2013-05-01 12:00:00     First Hi    2013-05-01 12:00:00
于 2013-05-01T17:21:30.240 回答