【问题标题】:Fetching products matching multiple attribute filters (entity attribute value)获取匹配多个属性过滤器的产品(实体属性值)
【发布时间】:2018-10-19 05:54:01
【问题描述】:

在从具有基本实体属性值模型的数据库中获取产品时,我正在尝试添加添加多个过滤器的可能性。过滤器基于以下属性值:

  • 颜色:绿色、红色
  • 尺寸:小号、大号

我对单个过滤器没有任何问题,但我不知道如何同时处理多个过滤器。


示例数据:(精简版)

SQL file with this example structure & data

产品

id name
1  jacket
2  shirt

product_variants

id product_id
1  1
2  2
3  2

属性

id name
1  colors
2  sizes

属性值

id attribute_id value
1  1            green
2  1            red
3  2            small
4  2            large

表格variant_details

id product_variant_id attribute_value_id
1  1                  3                    (jacket - small)
2  2                  1                    (shirt - green)
3  2                  3                    (shirt - small)
4  3                  1                    (shirt - green)
5  3                  4                    (shirt - large)

对于本示例,三个变体将是:

  • 夹克(小)
  • 衬衫(绿色和小号)
  • 衬衫(绿色和大号)

目标

我想传递属性值的 id 并获取与所有所述属性值匹配的产品,例如:

products.php?attr=1&4

应获取绿色 (1) 和大 (4) 的产品,例如,只有第三个变体符合条件,因此所需的结果是:

product_id product_desc
2          shirt

我的尝试

我认为这不会有太大帮助,但我只有一个属性:

products.php?attr=1

应该产生任何具有绿色 (1) 属性值的东西:

SELECT products.id, products.desc, attribute_value.value FROM products
LEFT JOIN product_variants ON products.id = product_variants.product_id
LEFT JOIN variant_details ON variant_details.product_variant_id = product_variants.id
LEFT JOIN attribute_value ON attribute_value.id = variant_details.attribute_value_id
WHERE attribute_value.id = 1
GROUP BY products.id

问题在于,在 WHERE 子句之前,它会产生以下内容:

id name    value
1  jacket  small
2  shirt   green
2  shirt   small
2  shirt   green
2  shirt   large

例如,我不知道如何过滤那些值列既绿色又大的行。我认为我对查询采取的方法是错误的。

任何帮助将不胜感激。

【问题讨论】:

  • SQL 的输入到底是什么? PS 有一个明显的观点是从 EAV 表中重构一个简单的非 EAV 表。 (EAV 表是一些简单表的元数据表。)然后对这些视图有一个明显的查询来给出你想要的。找到那些查询。 PS 如果适合您的目的,首选的 SQL 演示站点是 sqlfiddle.com。
  • use text, not images/links, for text (including code, tables & ERDs)。使用链接/图像仅是为了方便补充文本和/或无法在文本中给出的内容。永远不要给出没有图例/键的图表。如果您有代表,请使用编辑功能内联,而不是链接 - 使您的帖子独立。
  • 了解 LEFT JOIN 返回的内容:INNER JOIN 行加上由 NULL 扩展的不匹配的左表行。作为 LEFT JOIN 的一部分,始终知道您想要什么 INNER JOIN。在 LEFT JOIN ON 删除任何由 NULL 扩展的行之后,需要右表列不为 NULL 的 WHERE 或 ON,即只留下 INNER JOIN 行,即“将 LEFT JOIN 转换为 INNER JOIN”。你有那个。
  • 感谢所有 cmets philipxy。 1.- 查找将 EAV 表转换为简单明了的查询:好主意!我会调查的。 2.- 文本不是链接:知道了。我决定链接 sql,因为它似乎太多了,并且这里已经描述了表,但会考虑在内。 3.- JOIN 类型:将进一步研究,再次感谢!
  • 您希望此查询的视图和/或结果可能是 EAV。也许就像“产品 P 变体 V 具有属性 A 值 X”。但是您还没有阐明输入过滤器数据是如何进入 SQL 的。而且还不清楚它的“匹配”是什么。通过由列名参数化的语句模板来表征表(基本或查询结果)——它的 (特征)谓词——在表中生成真实语句的行。 PS 子行值出现在一个表中,所有子行值出现在另一个表中的表是Codd原来relational-division的结果。

标签: php mysql join filter entity-attribute-value


【解决方案1】:

我能够通过以下查询使其以某种方式工作:

SELECT products.id, products.desc FROM products
WHERE EXISTS 
(
SELECT * FROM product_variants
LEFT JOIN variant_details ON variant_details.product_variant_id = product_variants.id
LEFT JOIN attribute_value ON attribute_value.id = variant_details.attribute_value_id
WHERE product_variants.product_id = products.id AND attribute_value.id = 1
)
AND EXISTS
(
SELECT * FROM product_variants
LEFT JOIN variant_details ON variant_details.product_variant_id = product_variants.id
LEFT JOIN attribute_value ON attribute_value.id = variant_details.attribute_value_id
WHERE product_variants.product_id = products.id AND attribute_value.id = 4
)

我说在某种程度上是因为它会返回所有具有一个或多个变体中的每个请求属性的产品。 p>

示例

以单一产品为例,一件有两种颜色和两种尺码的衬衫,它的变体可能是:

  • 衬衫(绿色和小号)
  • 衬衫(绿色和大号)
  • 衬衫(红色和小号)

请注意没有红色和大的变体。如果我使用 red & large 进行上述查询,它仍然会匹配该产品,因为它的一个变体具有“红色”,而另一个变体具有“大”。

我决定将其添加为答案而不是编辑,因为它实现了将产品与两个(或更多)属性匹配的目标,但我仍然希望看到结果被限制为匹配单个属性的答案产品的变体,或者可能是实现此目的的另一种方式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 2011-07-19
    • 2019-02-12
    • 1970-01-01
    相关资源
    最近更新 更多