我有两张表Products
和ProductProperties
。
Products
name - string
description - text
etc etc
ProductProperties
product_id - integer
property_id - integer
还有一个表Properties
,它基本上存储了属性名称及其属性列表
如何实现一个SQL命令,用于查找具有property_ids(A或B或C)AND(X或Y或Z)的产品
我已经到了这里:
SELECT DISTINCT "products".*
FROM "products"
INNER JOIN "product_properties" ON "product_properties"."product_id" = "products"."id" AND "product_properties"."deleted_at" IS NULL
WHERE "products"."deleted_at" IS NULL
AND (product_properties.property_id IN ('504, 506, 403'))
AND (product_properties.property_id IN ('520, 501, 502'))
但它并没有真正起作用,因为它正在寻找一个既有值504也有520的产品属性,它永远不会存在。
非常感谢一些帮助!
答案 0 :(得分:2)
您需要在属性组的基础上定义中间结果集:
SELECT DISTINCT p.*
FROM products p
JOIN product_properties groupA ON groupA.product_id = p.id AND groupA.deleted_at IS NULL AND groupA.property_id IN ('504')
JOIN product_properties groupB ON groupB.product_id = p.id AND groupB.deleted_at IS NULL AND groupB.property_id IN ('520')
WHERE p.deleted_at IS NULL
你知道,你自己很好地发现了这个问题:"但它并没有真正起作用,因为它正在寻找一个既有504又有520的产品属性,它永远不会存在"
实际上,记录集在查询中是不可变的,应用于它们的所有单个条件都是一次性应用的。您需要复制每个表并对其应用单独的条件。
答案 1 :(得分:0)
一种方法使用exists
或in
:
select p.*
from products p
where p.id in (select pp.product_id
from product_properties pp
where pp.propertyid in ('504', '520')
);
这使您不必在外部查询中使用distinct
。
如果,实际上,您的意思是找到所有属性的产品,那么join
和group by
工作:
select p.*
from products p join
product_properties pp
on p.id = pp.product_id
where pp.propertyid in ('504', '520')
group by p.id -- yes, this is allowed in Postgres
having count(*) = 2;
答案 2 :(得分:0)
嗨试试这个查询我只是想着它所以我没有尝试任何一个检查我有想法我想做
SELECT DISTINCT "products".*
FROM products pr
WHERE id IN
(
SELECT product_id FROM ProductProperties WHERE property_id IN (504,520)
GROUP BY product_id
HAVING Count(*) = 2
) AND "products"."deleted_at" IS NULL
SELECT DISTINCT "products".*
FROM products pr, INNER JOIN (
SELECT product_id,count(*) as nbr FROM ProductProperties WHERE property_id IN (504,520)
GROUP BY product_id
) as temp ON temp.product_id = pr.id
WHERE "products"."deleted_at" IS NULL AND temp.nbr = 2
并且您也可以检查这个(您也可以使用where子句中的连接而不是使用INNER JOIN)
SELECT DISTINCT products.* FROM products as p
INNER JOIN product_properties as p1 ON p1.product_id = p.id
INNER JOIN product_properties as p2 ON p2.product_id = p.id
WHERE p.deleted_at IS NULL
AND p1.property_id = '504' AND p1.deleted_at IS NULL
AND p2.property_id = '520' AND p2.deleted_at IS NULL