2010-08-30 200 views
2

我在查詢時遇到了問題。我試過子查詢,不同的連接和group_concat(),但它們要麼不工作要麼很痛苦。這可能有點複雜的解釋,但這裏的問題:mysql select - 子查詢,group_concat()不工作/太慢

我有一個表「項目」(約2000產品)。我有一個表「標籤」(其中包含大約2000個不同的產品標籤)。我有一個「tagassign」表(將標籤連接到項目,大約有200000條記錄)。

我使用標籤來定義產品的特徵,例如顏色,兼容性,產品是否特價等。現在,如果我希望能夠顯示分配有特定標籤的產品他們,我使用一個簡單的查詢,如:

select * from item, tagassign 
    where item.itemid = tagassign.itemid 
    and tagassign.tagid = "specialoffer" 

問題是,我可能想看到有幾個標籤的項目。例如,我可能只想看到與Apple iPhone兼容的黑色手機外殼,並且是新的。所以我基本上希望看到項目表中的所有記錄都有「黑色」和「大小寫」,「iphone」和「新」的標籤。唯一可以實現這個功能的方法是創建4個別名(select * from item,tagassign,tagassign as t1,tagassign as t2,tagassign as t3等)。在某些情況下,我可能會尋找10或20個不同的標籤,並且有很多記錄,查詢速度非常慢。

我知道我錯過了一些明顯的東西。有任何想法嗎? 謝謝!

+0

向我們展示您的'EXPLAIN SELECT' - 索引? – Piskvor 2010-08-30 21:03:49

回答

3
SELECT * 
FROM item i 
WHERE (
     SELECT COUNT(*) 
     FROM tagassign ta 
     WHERE ta.tagid IN ('black', 'case', 'iphone', 'new') 
       AND ta.itemid = i.itemid 
     ) = 4 

用您正在搜索的標籤的實際數量而不是4替代。

tagassign (itemid, tagid)(按此順序)上創建一個唯一索引或主鍵,以便快速工作。

如果您正在尋找大量的標籤(或很少使用的標籤),此查詢也更快:

SELECT i.* 
FROM (
     SELECT itemid 
     FROM tagassign ta 
     WHERE ta.tagid IN ('black', 'case', 'iphone', 'new') 
     GROUP BY 
       itemid 
     HAVING COUNT(*) = 4 
     ) t 
JOIN item i 
ON  i.itemid = t.itemid 

對於此查詢,則需要在tagassign (tagid, itemid)唯一索引。

+0

對語法選擇感到好奇 - 爲什麼不使用EXISTS並指定'HAVING COUNT(DISTINCT ta.tagid)= 4'?當我發表評論時,它不在那裏,我發誓... – 2010-08-30 21:10:46

+0

@OMGPonies:由於索引是唯一的,所以'COUNT(*)'只會計算匹配記錄,每個記錄一次。 「EXISTS」在那裏會過度殺傷。不過,爲了完整起見,我會對它做出迴應:) – Quassnoi 2010-08-30 21:14:32

+0

+1:我錯過了第一個選項 – 2010-08-30 21:18:42