我有以下表格:
Option
-------
id - int
name - varchar
Product
---------
id - int
name -varchar
ProductOptions
------------------
id - int
product_id - int
option_id - int
如果我有一个选项 id 列表,我如何检索所有具有我拥有的 id 列表的所有选项的产品?我知道 SQL“IN”将使用“OR”,我需要“AND”。谢谢!
我有以下表格:
Option
-------
id - int
name - varchar
Product
---------
id - int
name -varchar
ProductOptions
------------------
id - int
product_id - int
option_id - int
如果我有一个选项 id 列表,我如何检索所有具有我拥有的 id 列表的所有选项的产品?我知道 SQL“IN”将使用“OR”,我需要“AND”。谢谢!
如果您有 ID 列表,则基本上只有 2 个选项。
- 要么调用尽可能多的选择,
要么你必须使用 IN () 或 OR。
但是,建议使用 IN ,因为调用一个语句通常性能更高(此外,如果您对所有 id 列都有索引,则不需要进行表扫描)。
我会使用以下语句:
select Product.* from Product, Option, ProductOption where Option.id IN ( 1, 2, ... ) and option.id = ProductOption.option_id and Product.product_id = Product.id
再说一句,为什么 ProductOptions 表中有 id 列?从我的角度来看,这没用,您应该从 product_id 和 option_id 列中获得复合主键(因为这对是唯一的)。
如果 id 不重复,您可以检索您需要的选项的 id 并计算它们的数量。那么,你只要
SELECT product_id FROM ProductOptions
WHERE option_id IN ( OPTIONS )
GROUP BY product_id
HAVING COUNT(product_id) = NEEDED;
如果没有 GROUP BY,如果您有五个选项 ID,并且产品 27 有十五个选项,其中有五个选项,您将获得具有相同 product_id 的五行。GROUP BY 连接这些行。由于您想要所有选项,并且选项具有所有不同的 ID,因此询问“具有所有选项的行”等同于询问“具有与所需选项集大小一样多的选项的行”。
另外,您只在 ProductOptions 上运行大查询,这应该非常快。
处理此类查询的一种方法是使用 group by 和 having 子句。最好从列表中的必需选项列表开始:
with list as (
select <optionname1> as optionname union all
select <optionname2 union all . . .
)
select ProductId
from list l left outer join
Options o
on l.optionname = o.name
ProductOptions po join
on po.option_id = o.option_id left outer join
group by ProductId
having count(distinct o.optionname) = count(distinct l.optionname)
这保证了所有都在列表中。顺便说一句,我使用 SQL Server 语法来生成列表。
如果您有其他格式的列表,例如分隔字符串,还有其他选项。根据您使用的数据库,还有其他可能性。但是,上述想法应该适用于任何数据库,但有两个警告:
Will this work?:
select p.id, p.name
from Product as p inner join
ProductOptions as po on p.id=po.product_id
where po.option_id in (1,2,3,4)