2016-03-07 105 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') 
) 
;