2011-02-02 48 views
2

我真的不知道如何短語的問題,所以讓我給這個問題的一個例子:PHP/MySQL的:許多一對多/交叉表問題

假設有它映射項的表格分類。每個項目可以有任意數量的類別,每個類別當然可以包含任意數量的項目。所以,你有一個表,如下所示:

items_categories

ID ITEM_ID CATEGORY_ID

的問題是,我想選擇所有項目的ID具有特定類別的ID。例如,選擇category_id's爲1和2的所有item_id's:我想查找與類別1和2相關聯的所有項目。顯然,我不能使用AND語句,並且OR語句將返回所有item_id與任一類別,但不一定都是。

這裏是我的解決方案和我能想到的最好的東西:選擇category_id等於1或2的所有item_id;迭代PHP中的結果並跟蹤有多少item_ids與category_id關聯;然後取消設置沒有指定數量類別的結果中的所有item_id。下面是我的代碼片段:

// assume $results is an array of rows from the db 
// query: SELECT * FROM items_categories WHERE category_id = 1 OR category_id = 2; 
$out = array(); 
foreach ($results as $result) 
{ 
    if (isset($out[$result['item_id']])) 
     $out[$result['item_id']] ++; 
    else 
     $out[$result['item_id']] = 1; 
} 
foreach ($out as $key=>$value) 
{ 
    if ($value != 2) 
     unset($out($key)); 
} 
return array_keys($out); // returns array of item_ids 

顯然,如果你有很多不同的類別,你選擇和處理方式應該比你理論上需要更多的信息。有任何想法嗎?

謝謝!

編輯:這裏有一個表和信息的一個例子,我想從它:

​​

所以說,我感興趣的是讓所有的物品與第1類和2我如何因爲我只想要類別爲#1 #2的物品,所以從我的示例表中獲取物品#1?如果我選擇類別1 2(如上例所示),我必須在這種情況下選擇整個表格,並「手動」刪除item_id的2和3,因爲它們不與類別1和類別2.希望這有助於澄清一點。

最終編輯:我明白了,儘管我明顯無法描述我正在嘗試做什麼,嘿。這是我想出了查詢,備案:

SELECT * 
FROM 
(
    SELECT item_id, COUNT(*) as count 
     FROM items_categories 
     WHERE category_id IN (1, 2) 
    GROUP BY item_id 
) table_count 
WHERE count = 2; 

在這種情況下, 「(1,2)」 可能被替換爲 「( category_id1 category_id2,...)」 ,最後的「2」將被我正在搜索的類別數量所取代。

因此,它會找出有多少類別符合每件商品的標準,並且由於我只希望所有商品類別都匹配的商品,因此只會選擇類別數量等於我要查找的商品類別數量的商品。這當然假設沒有重複的類別或類似的東西。

感謝您的回覆!

回答

1

看來,什麼是困擾你的是,你不得不做,當然這需要O(n)的時間線性搜索,但如果你選擇的排序順序從數據庫元素,那麼你就不能使用O(lg n)時間的二進制搜索?

我希望這可以幫助,如果沒有,那麼也許我誤解你的問題,我想請你澄清這一點。

+0

感謝您的回覆。事情是,我沒有在結果中尋找具體的價值 - 我只是想從我的結果中知道每個項目有多少種類與之相關聯。如果該數字與我正在搜索的類別數量不同,那麼我會知道該項目不包含所有類別。如果我正確理解這一點,我認爲二進制搜索不會真的實現這一點,因爲我沒有尋找具體的價值。 – user599599 2011-02-02 08:10:34

+0

順便說一句,我編輯了我原來的帖子,希望能夠讓它更清楚一點。 – user599599 2011-02-02 08:17:36

0
SELECT 
foo 
FROM 
bar 
WHERE 
foo IN (1,2) 

這是你在找什麼?

+0

,基本上實現了通過選擇其中foo = 1或富= 2。換句話說,它的清潔是我的意思,但我必須做在PHP數組處理同樣數量的過濾出結果,其中「富」 ISN (當然,這是不可能的,因爲對於任何給定的行,「foo」有一個值,但在我的情況下,我期望多行具有相同的item_id和一組category_id)。 – user599599 2011-02-02 08:14:50

0

這是你應該得到的數據庫來做,而不是PHP。

SELECT item_id     # We want a list of item ids 
FROM cat_items     # Gets the item ID list from the cat_items table 
WHERE cat_id IN (1, 2, 7, 11) # List of categories you want to search in 
GROUP BY item_id;    # As the same item can appear in more than one category this line will eliminate duplicates 

此查詢並假設在cat_items的數據是準確的,在該類別和項目ID指向分別在類別和項目表中的有效條目等字樣。如果你使用的是支持外鍵的數據庫(MySQL的InnoDB引擎,Postgres等),那麼執行外鍵並不困難。

要獲得ID列表中你想要的格式每個類別,這是很容易在SQL端完成了。

SELECT * 
FROM cat_items 
WHERE cat_id IN (1, 2, 7, 11) 
GROUP BY cat_id, item_id; 

如果你只是想有多少項目在每個類別的計數,你也可以做,在SQL

SELECT cat_id, COUNT(item_id) AS items 
FROM cat_items 
WHERE cat_id IN (1, 2, 7, 11) 
GROUP BY cat_id; 

如果你需要的不僅僅是ID更多的數據,那麼你可以加入反對你需要來自你的數據表。

SELECT items.* 
FROM cat_items 
JOIN items ON cat_items.item_id = items.id 
WHERE cat_id IN (1, 2, 7, 11) 
GROUP BY item_id; 
+0

感謝您的答覆 - 事情是,這將返回在*你給它的類別中的任何*的項目,我感興趣的是在* *所有類別的項目。無論如何,你的計數查詢讓我思考並導致解決問題。我只需要計算每個項目匹配的類別數量,並確保這與我正在查找的類別數量相等。 – user599599 2011-02-02 20:26:37

0
SELECT item_id FROM items_categories WHERE category_id = 1 AND item_id IN (SELECT item_id FROM items_categories WHERE category_id = 2)