基于表本身和不同表

时间:2016-10-09 20:43:05

标签: php mysql

我有一个问题,我正在建立一个论坛,我遇到了以下问题。

我有2张桌子

table: topics

topic_id | name    | timestamp           | pinned
-------------------------------------------------
1        | topic_1 | 2016-01-01 12:00:00 | 0
2        | topic_2 | 2016-01-01 13:00:00 | 0
3        | topic_3 | 2016-01-01 14:00:00 | 1
4        | topic_4 | 2016-01-01 15:00:00 | 0
5        | topic_5 | 2016-01-01 16:00:00 | 0

table: messages

message_id | topic_id | text | timestamp
---------------------------------------------------
1          | 1         | test | 2016-01-01 12:30:00
2          | 2         | test | 2016-01-01 13:30:00
3          | 2         | test | 2016-01-01 13:45:00
4          | 1         | test | 2016-01-01 14:30:00
5          | 4         | test | 2016-01-01 17:30:00

正如您所看到的,主题#1有2条消息,主题#2也有2条消息,主题#4 1条消息,主题#3和#5根本没有消息。

我想在PINNED和TIMESTAMP上订购它们。怎么样?

- >如果某个主题被固定,那么它必须位于顶部

- >如果主题有消息,请在最后消息的时间戳上对它们进行排序

- >如果主题没有任何消息,请在主题本身的时间戳上对它们进行排序

上面的例子,顺序是(从上到下):

topic_3 (pinned so ALWAYS at the top)
topic_4 (last message at 17:00:00)
topic_5 (no messages but started at 16:00:00)
topic_1 (last message at 14:30:00)
topic_2 (last message at 13:45:00)

我希望我的问题很清楚。

希望有人可以提供帮助!

提前致谢。

编辑:

我尝试了以下但是这不起作用

SELECT DISTINCT 
        t.topic_id,
        t.name 
FROM 
        topics AS t 
LEFT JOIN messages AS m ON m.topic_id = t.topic_id 
ORDER BY 
        t.pinned DESC, 
        m.timestamp DESC,
        t.timestamp DESC

1 个答案:

答案 0 :(得分:1)

由于一个主题附加了许多消息,您需要使用具有MAX(时间戳)的消息进行排序,因此您的任务变得复杂。 DISTINCT因为从表中取出随机记录而无法工作。

我不得不使用子查询来解决问题。如果消息时间戳不为NULL,则IFNULL将返回消息时间戳,否则为 - 任务所需的主题时间戳。

SELECT
        t.topic_id,
        t.name,
        IFNULL(m.timestamp, t.timestamp)
FROM 
        topics AS t 
LEFT JOIN
(SELECT
    messages.topic_id,
    MAX(messages.timestamp) as timestamp
FROM
    messages
GROUP BY
    messages.topic_id
) AS m
  ON m.topic_id = t.topic_id
GROUP BY
      t.topic_id
ORDER BY 
        t.pinned DESC, 
        IFNULL(m.timestamp, t.timestamp) DESC;

输出:

+----------+---------+----------------------------------+
| topic_id | name    | IFNULL(m.timestamp, t.timestamp) |
+----------+---------+----------------------------------+
|        3 | topic_3 | 2016-01-01 14:00:00              |
|        4 | topic_4 | 2016-01-01 17:30:00              |
|        5 | topic_5 | 2016-01-01 16:00:00              |
|        1 | topic_1 | 2016-01-01 14:30:00              |
|        2 | topic_2 | 2016-01-01 13:45:00              |
+----------+---------+----------------------------------+

如有必要,删除时间戳,我曾经表明查询会获取正确的记录。