0

对于我遇到的问题,以下数据库模型是相关的:商店有零个或多个评级。评级有零个或多个消息。这意味着评级具有外键 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 对其进行排序)
  2. 我不明白为什么我需要进行两次连接才能获得每条消息的最新评级
4

2 回答 2

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 = "unread"),但您还需要考虑到您可能找不到满足条件但仍需要当前列的适当关联(在我的情况下针对 message.status 的测试为 NULL)
  2. 由于 LEFT JOIN,您还需要 GROUP BY 主对象的主键,这样您就不会得到重复
  3. 您需要使用 GREATEST 来获取主对象和关联对象的属性的最高值。如果您的数据中有 NULL 值,则还需要针对 IFNULL 进行测试。

我将尝试更新我的解释,使其更加明显。我希望该解决方案对其他人有所帮助。

于 2013-07-25T10:26:44.797 回答
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
于 2013-07-24T09:37:50.660 回答