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

これは機能しますが、アイテムが誰かのウィッシュリストに追加さ、レビューが投稿された場​​合、そのアイテムは2回返されます。UNION通常は重複を削除しdateますが、2つの行が異なるため、両方の行が返されます。重複する行を削除するときに日付を無視するように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

しかし、それは何らかの理由でめちゃくちゃ遅いことが判明しました(約30分かかりました)。

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 を含む述語のためにおそらく非常に遅くなりました。データベースに 3 つのテーブルを結合するように要求し、その結果のタイムスタンプ情報を調べました。私のステートメントは、より小さな中間テーブルを形成する必要があります。反応もウィッシュリストもないアイテムは日付が 0 になり、おそらくレポートされません。

于 2009-10-02T00:10:31.157 に答える