2016-03-07 104 views
0

中選擇行我有一個表的「產品」與產品名稱和ID:包括在一組從其他表

id | title 
1  product 1 
2  product 2 

每個產品可以有一系列的標籤。標籤在表「屬性」鑑定:

id | name  | handle 
1  Tag One tag-one 
2  Tag Two tag-two 
3  Tag Three tag-three 
4  Tag Four tag-four 
etc 

標記關係的產品是另一個表「標籤」:

id | AttId | OwnerId 
1  1  1 
2  2  1 
3  1  2 
4  3  2 
etc 

好了,所以我想選擇一組都有產品至少一個特定標籤以及其他標籤的可能選擇。這是我現在正在處理的內容:

SELECT products.id 
FROM products 
WHERE 
EXISTS 
( 
    SELECT 1 
    FROM Tags 
    INNER JOIN Attributes ON tags.AttId = Attributes.id 
    WHERE Attributes.handle = 'tag-one' 
    AND (
      Attributes.handle = 'tag-two' 
      OR 
      Attributes.handle = 'tag-four' 
     ) 

    AND products.id = Tags.OwnerId 
) 

如果我刪除AND(OR)部分,查詢就可以工作。如上所述,它顯示沒有錯誤,但也沒有結果;我應該如何寫這個,這樣我就可以得到一套確實有一個標籤的產品,並且通過標籤手柄有/或其他指定的標籤?

回答

2

我喜歡用group byhaving來處理這種類型的問題 - 因爲我發現這種方法很適合表達許多不同的條件。爲了您的條件:

select p.* 
from products p join 
    tags t 
    on t.OwnerId = p.id join 
    attributes a 
    on t.attid = a.id 
group by p.id 
having sum(a.handle = 'tag-one') > 0 and 
     sum(a.handle in ('tag-two', 'tag-four')) > 0; 

having子句中每個條件計算行的匹配條件數(產品)。首先說至少有一行用'tag-one'句柄。第二個說,至少有一行與另外兩個手柄。

0

我想,如果執行兩個單獨的查詢和取交集,那會給你想要的東西。

-- Get all the owner ids that have 'tag-one' 
select OwnerId 
from Tags t1 
where AttId in 
(
    select id 
    from Attributes a1 
    where a1.handle = 'tag-one' 
) 
intersect 
-- Get all the owner ids that have tag-two and tag-four 
select OwnerId 
from Tags t2 
where AttId in 
(
    select id 
    from Attributes a2 
    where a2.handle in ('tag-two', 'tag-four') 
) 
;