2009-10-01 99 views
2

我有一個MySQL查詢來獲取最近有活動的項目。基本上,用戶可以發佈評論或將其添加到他們的願望清單中,並且我想要獲得所有在最近x天內都有新評論或者被放置在某人的願望清單上的項目。在使用UNION時擺脫MySQL查詢中的重複結果

查詢去有點像這樣(略簡體):

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 

但是,這竟然是出於某種原因出奇的慢(花了大約半分鐘)。

+0

你需要顯示日期嗎? – Buggabill 2009-10-01 12:48:26

+0

不,日期僅用於排序。 – Aistina 2009-10-01 12:53:20

回答

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 

雖然我知道這可能並沒有考慮到這是迄今爲止最高的爲每個項目...還不確定,如果該事項,如果是這樣,做些什麼。

+0

自5.7版以來,ONLY_FULL_GROUP_BY模式將默認啓用,並且啓用該模式將不再可能。 – mikiqex 2016-03-27 13:50:07

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, ... 
+0

這給我只有1個結果(最新)。 – Aistina 2009-10-01 13:23:09

+0

如果我正確理解這一點,當它們出現在反應和願望清單表中時,您會得到重複的項目。當一個項目出現在兩個表中時,這將給你最新的日期,並且當它只出現在其中一個表中時,它不會產生任何影響。請務必不要在'group by'中包含日期。 – 2009-10-01 13:32:59

+0

MAX函數使它只返回一個結果......但我根據你的建議自己解決了它。我會在一秒之內發佈我所做的。 – Aistina 2009-10-01 13:44:33

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的日期,這可能會導致它們不被報告。

+0

謝謝,但你的建議仍然比我的解決方案慢10倍以上。 +1教我關於最偉大的和COALESCE功能雖然! – Aistina 2009-10-06 13:45:09