2010-02-22 119 views
2

我有兩個表。一個是items,另一個是tags。查詢的hereMysql Join Query多次給出相同的結果

這個想法是創建一個搜索框來搜索項目,然後通過選擇標籤縮小搜索範圍。 (某種分面搜索)。

與MySQL教程擺弄左右後,我想出了這個:

SELECT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
WHERE (
    (`tags`.`type`='food' AND `tags`.`name`='pizza') 
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
    --And so on for every tag 
) 
ORDER BY `pay` DESC LIMIT 0 , 30 

(我刪除查詢全文搜索,因爲它是不相關的現在)

它工作得不錯,但我有兩個問題:

  1. 如果用戶不選擇任何標籤,每一個有更多然後1個標籤項目連接到它顯示了更多的則1次
  2. 如果用戶選擇兩個標籤,例如食品=>披薩和飲料=>檸檬水,每個包含披薩或檸檬水的食品或兩者都會出現,我只想要那些帶有這些標籤的食品。

是否有可能用不同的mysql查詢解決這些問題?或者我應該在php代碼中修復這些問題。 (或者我是否完全錯了,是否有更好的方式來使用標籤?)

希望我自己清楚。

GR,

巴斯

回答

2

扔在SELECT後的關鍵字DISTINCT?

SELECT DISTINCT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
WHERE ( 
    (`tags`.`type`='food' AND `tags`.`name`='pizza') 
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
    --And so on for every tag 
) 
ORDER BY `pay` DESC LIMIT 0 , 30 

至於你的第二個問題......你的邏輯是錯的。如果我理解正確的話,你想通過items.id組,然後拒絕不具有相同的行數爲選擇標籤的數量...也許像回來的物品:

SELECT DISTINCT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
    FROM `items`LEFT JOIN (`tags`) ON (`tags`.`item_id`=`items`.`id`) 
    WHERE ( 
     (`tags`.`type`='food' AND `tags`.`name`='pizza') 
     OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade') 
     --And so on for every tag 
    ) 
    GROUP BY `items`.`id` 
    HAVING COUNT(*) = 2 
    ORDER BY `pay` DESC LIMIT 0 , 30 

...並將HAVING COUNT(*)= 2中的2替換爲您嘗試同時匹配的標籤的數量...

+0

謝謝,最後的查詢工作完美! – Bas 2010-02-22 17:11:37

+0

順便說一句,這是不錯的MySQL實踐? – Bas 2010-02-22 17:12:41

+0

這是一個很難回答的問題...就性能而言,只要你設置了合適的索引就可以了......我的觀點是,如果它一貫正確地工作,並且對於你的應用程序來說'速度夠快',那就去吧。 – vicatcu 2010-02-22 18:07:36

1

嘗試WHERE tag.id IN(SUBQUERY)

SELECT `items`.`id`, `items`.`name`, `items`.`pay`, `items`.`desc` 
FROM `items` WHERE items.id IN (SELECT DISTINCT item_id 
    FROM tags 
    WHERE (
    (`tags`.`type`='food' AND `tags`.`name`='pizza') 
    OR (`tags`.`type`='drinks' AND `tags`.`name`='lemonade')) 
    --And so on for every tag 
) 
ORDER BY `pay` DESC LIMIT 0 , 30 
+0

解決了克隆結果的問題,但是當用戶選擇多於一個標籤時,它不會返回具有兩個標籤的項目。相反,它只是返回每個項目與其中一個選定的標籤。有任何想法嗎? – Bas 2010-02-22 17:01:04

+0

如果你只想要比薩和檸檬水的項目,只需將您的OR更改爲AND。這也適用於Vicatcu的方法,如果您希望全部使用這些標籤,則無需統計多少個標籤。 – MindStalker 2010-02-22 18:35:49

+0

這不起作用。每個標籤/類型組合都有自己的行。所以 SELECT DISTINCT item_id FROM tags WHERE('tags'.'type' ='food'AND'tags'.'name' ='pizza') AND('tags'.'type' ='drinks 'AND' tags'.'name' ='lemonade')) 根本不會返回任何結果,因爲一行不能包含兩個類型和名稱的值。 – Bas 2010-02-24 12:25:24