我假设 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;