0

我有这样的桌子

 - Products: PID,ProductName...
 - Attributes:AID,AttributeName...
 - ProductAttributes:PID,AID,Value

值是

***ProductAttributes***

 - P1,A1,V1
 - P1,A2,V2
 - P1,A3,V3
 - P2,A1,V4
 - P2,A2,V2
 - P2,A3,V3
 - P3,A1,V1
 - P3,A2,V2
 - P3,A3,V5

我需要一个具有 2 个数组参数的过程,并通过这些参数过滤产品。如果Parameter1:{A1,A2}Parameter2:{V1,V2}程序应该选择

P1,P3

我怎么写这个?谢谢

4

1 回答 1

0

我假设 V1 必须是属性 A1 的值,而 V2 必须是属性 A2 的值。换句话说,如果您搜索具有属性('canvascolor'、'solecolor')和值('red'、'black')的鞋子,那么您不会想要黑色帆布和红色鞋底的鞋子。

每当您想比较 WHERE 表达式中的多个属性时,它们都需要位于同一行。如果您有一个传统的关系表设计,这将很容易,其中每个属性都存储在不同的列中:

SELECT p.*
FROM Products p
WHERE p.canvascolor = 'red' AND p.solecolor = 'black';

你也可以用元组比较来写这个表达式:

SELECT p.*
FROM Products p
WHERE (p.canvascolor, p.solecolor) = ('red', 'black');

当您将属性存储在多行上时,就像您正在使用的这个实体-属性-值表一样,事情会变得更加复杂。这是 EAV 赋予您随意定义属性的灵活性的权衡。您需要使用连接将它们放在同一行上,以便进行比较:

SELECT p.*
FROM Products p
JOIN ProductAttributes pa1 ON pa1.PID = p.PID
JOIN Attributes a1 ON a1.AID = pa1.AID
JOIN ProductAttributes pa2 ON pa2.PID = p.PID
JOIN Attributes a2 ON a2.AID = pa2.AID
WHERE (a1.AttributeName, pa1.Value) = ('A1', 'V1')
 AND (a2.AttributeName, pa2.Value) = ('A2', 'V2');

另一种方法是匹配一属性/值对,然后按匹配的 PID 分组。匹配数恰好为两个的组具有所需的属性和值。

SELECT p.PID, MAX(p.ProductName), ...
FROM Products p
JOIN ProductAttributes pa ON pa.PID = p.PID
JOIN Attributes a ON a.AID = pa.AID
WHERE (a.AttributeName, pa.Value) = ('A1', 'V1')
 OR (a.AttributeName, pa.Value) = ('A2', 'V2')
GROUP BY p.PID
HAVING COUNT(*) = 2;
于 2012-11-01T19:08:44.173 回答