2

我有一个 MySQL 查询来获取最近有活动的项目。基本上,用户可以发布评论或将其添加到他们的愿望清单中,我想获取在过去 x 天内有新评论或被放置在某人的愿望清单中的所有项目。

查询有点像这样(稍微简化):

SELECT items.*, reaction.timestamp AS date FROM items
LEFT JOIN reactions ON reactions.item_id = items.id
WHERE reactions.timestamp > 1251806994
GROUP BY items.id

UNION

SELECT items.*, wishlists.timestamp AS date FROM items
LEFT JOIN wishlist ON wishlists.item_id = items.id
WHERE wishlists.timestamp > 1251806994
GROUP BY items.id

ORDER BY date DESC LIMIT 5

这是可行的,但是当一个项目同时被放置在某人的愿望清单中发布了评论时,该项目会被退回两次。UNION正常删除重复项,但由于date两行之间的差异,两行都返回。我可以以某种方式告诉 MySQL 在删除重复行时忽略日期吗?

我也尝试做这样的事情:

SELECT items.*, IF(wishlists.id IS NOT NULL, wishlists.timestamp, reactions.timestamp) AS date FROM items
LEFT JOIN reactions ON reactions.item_id = items.id
LEFT JOIN wishlist ON wishlists.item_id = items.id

WHERE (wishlists.id IS NOT NULL AND wishlists.timestamp > 1251806994) OR
(reactions.id IS NOT NULL AND reactions.timestamp > 1251806994)
GROUP BY items.id

ORDER BY date DESC LIMIT 5

但由于某种原因,结果非常缓慢(大约花了半分钟)。

4

3 回答 3

5

根据 larryb82 的想法,我自己解决了这个问题。我基本上做了以下事情:

SELECT * FROM (
    SELECT items.*, reaction.timestamp AS date FROM items
    LEFT JOIN reactions ON reactions.item_id = items.id
    WHERE reactions.timestamp > 1251806994
    GROUP BY items.id

    UNION

    SELECT items.*, wishlists.timestamp AS date FROM items
    LEFT JOIN wishlist ON wishlists.item_id = items.id
    WHERE wishlists.timestamp > 1251806994
    GROUP BY items.id

    ORDER BY date DESC LIMIT 5
) AS items

GROUP BY items.id
ORDER BY date DESC LIMIT 5

虽然我意识到这可能没有考虑到每个项目的最高日期......尚不确定这是否重要,如果重要,该怎么办。

于 2009-10-01T14:31:03.493 回答
1

不确定这是否会对性能造成巨大影响,但您可以尝试

SELECT item_field_1, item_field_2, ..., max(date) as date
FROM
  (the query you posted) 
GROUP BY item_field_1, item_field_2, ...
于 2009-10-01T13:03:50.153 回答
1

我认为您根本不需要 UNION 。


SELECT item.*, GREATEST(COALESCE(wishlists.timestamp, 0), COALESCE(reaction.timestamp, 0)) as date
FROM items
LEFT JOIN reactions ON reactions.item_id = items.id AND reactions.timestamp > 1251806994
LEFT JOIN wishlists ON wishlists.item_id = items.id AND wishlists.timestamp > 1251806994
ORDER BY date DESC limit 5

您使用上面的 LEFT JOIN 可能非常慢,因为其中包含 OR 的谓词。您要求数据库将三个表连接在一起,然后检查该结果以获取时间戳信息。我的语句应该形成一个较小的中间表。没有反应或愿望清单的项目将获得日期 0,这可能会导致它们不被报告。

于 2009-10-02T00:10:31.157 回答