从另一个 table 中选择包含在一个集合中的行
Selecting rows that are included in a set from another table
我有一个 table "Products" 产品名称和 ID:
id | title
1 product 1
2 product 2
每个产品都可以有一系列标签。标记在 table "Attributes":
中标识
id | name | handle
1 Tag One tag-one
2 Tag Two tag-two
3 Tag Three tag-three
4 Tag Four tag-four
etc
产品标签关系是另一个 table "Tags":
id | AttId | OwnerId
1 1 1
2 2 1
3 1 2
4 3 2
etc
好的,所以我正在尝试 select 一组产品,这些产品都至少有一个特定标签,并且可能 select 离子其他标签。这是我现在正在使用的:
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) 部分,则查询有效。如上,显示没有错误,也没有结果;我应该如何写这个,这样我才能得到一组肯定有一个标签的产品,并且标签句柄有 either/or 其他指定的标签?
我喜欢使用 group by
和 having
来解决这类问题 -- 因为我发现这种方法对于表达许多不同的条件非常有效。针对您的条件:
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'
句柄。第二个说至少有一排有另外两个句柄。
我想如果你执行两个单独的查询并取交集,那将给你你想要的。
-- 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')
)
;
我有一个 table "Products" 产品名称和 ID:
id | title
1 product 1
2 product 2
每个产品都可以有一系列标签。标记在 table "Attributes":
中标识id | name | handle
1 Tag One tag-one
2 Tag Two tag-two
3 Tag Three tag-three
4 Tag Four tag-four
etc
产品标签关系是另一个 table "Tags":
id | AttId | OwnerId
1 1 1
2 2 1
3 1 2
4 3 2
etc
好的,所以我正在尝试 select 一组产品,这些产品都至少有一个特定标签,并且可能 select 离子其他标签。这是我现在正在使用的:
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) 部分,则查询有效。如上,显示没有错误,也没有结果;我应该如何写这个,这样我才能得到一组肯定有一个标签的产品,并且标签句柄有 either/or 其他指定的标签?
我喜欢使用 group by
和 having
来解决这类问题 -- 因为我发现这种方法对于表达许多不同的条件非常有效。针对您的条件:
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'
句柄。第二个说至少有一排有另外两个句柄。
我想如果你执行两个单独的查询并取交集,那将给你你想要的。
-- 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')
)
;