MySQL:ORDER BY,它使用最新关联对象的自有属性或属性

时间:2013-07-24 09:31:05

标签: mysql associations sql-order-by

对于我遇到的问题,以下数据库模型是相关的:商店的评级为零或更高。评级包含零个或多个消息。表示评级具有外键store_id,并且消息具有外键rating_id。

我们过去常常查询按其状态排序的所有评级(读取与未读),其次按其创建的时间戳排序:

// currenty query with simple order by
SELECT *
FROM rating rating
WHERE rating.store_id = $storeId
ORDER BY status DESC, created_timestamp DESC;

现在我们想要考虑评级信息。消息的评级应根据最新消息的created_timestamp 进行排序,具体取决于该消息的状态(读取与未读)。我想在一个查询中选择所有评级(有和没有消息)。

我很难将问题抽象为一个众所周知的问题集。有人能指出我正确的方向吗?


更新

在Barmar的帮助下,我创建了以下查询:

SELECT *
FROM rating r
LEFT JOIN (SELECT m.rating_id, m.created_timestamp, m.status
           FROM messages m
           JOIN (SELECT rating_id, MAX(created_timestamp) maxtime
                 FROM messages
                 GROUP BY rating_id) mmax
           ON m.rating_id = mmax.rating_id AND m.created_timestamp = mmax.maxtime) m
ON m.rating_id = r.id
ORDER BY m.status DESC, m.created_timestamp DESC

但是我对该解决方案有两个问题:

  1. 当评级没有相关消息时,它不会处理这种情况(在这种情况下,我希望按照评级本身的状态和created_timestamp进行orderey)。
  2. 我不明白为什么我需要做两个连接以获得每条消息的最新评级

2 个答案:

答案 0 :(得分:0)

SELECT *
FROM rating r
LEFT JOIN (SELECT m.store_id, m.created_timestamp, m.status
           FROM messages m
           JOIN (SELECT store_id, MAX(created_timestamp) maxtime
                 FROM messages
                 GROUP BY store_id) mmax
           ON m.store_id = mmax.store_id AND m.created_timestamp = mmax.maxtime) m
ON m.store_id = r.store_id
ORDER BY m.status DESC, m.created_timestamp DESC

答案 1 :(得分:0)

在一些朋友的帮助下,我实际上找到了一个有效的解决方案。这与Barmar提到的方法完全不同,但它解决了确切的问题:

SELECT CASE WHEN (rating.status = "unread") 
THEN GREATEST(IFNULL(max(message.created_timestamp),0), rating.created_timestamp )
ELSE max(message.timestamp_ created) END
AS message_rating_timestamp_unread,
rating.status, rating.created_timestamp AS rating_created_timestamp
FROM rating
LEFT join message
ON message.rating_id =  rating.id
WHERE(message.status = "unread" OR message.status is NULL)
GROUP BY rating.id
ORDER BY message_rating_timestamp_unread DESC, rating_created_timestamp DESC;

让我尝试抽象问题并引导您完成解决方案,以便它可以帮助其他人。在我的情况下,评级是主要对象,消息是评级的关联对象:

  1. 显然需要LEFT JOIN到相关对象。您需要针对条件进行测试(在我的情况下,message.status ="未读"),但您还需要考虑到您可能找不到满足条件的适当关联,但仍需要您当前的条件column(在我的情况下针对message.status的测试为NULL)
  2. 由于LEFT JOIN,您还需要GROUP BY您主要对象的主键,以便您不会重复
  3. 您需要使用GREATEST来获取主对象和关联对象的属性的最高值。如果您的数据中包含NULL值,则还必须对IFNULL进行测试。
  4. 我会尝试更新我的解释,使其更加明显。我希望这个解决方案可以帮助其他人。