我有一个PRODUCTS
表,每个产品可以有多个属性,所以我有一个ATTRIBUTES
表,另一个名为ATTRIBPRODUCTS
的表位于中间。属性被分组为类(类型,品牌,材料,颜色等),因此人们可能想要来自特定品牌的特定类型的产品。
PRODUCTS
product_id
product_name
ATTRIBUTES
attribute_id
attribute_name
attribute_class
ATTRIBPRODUCTS
attribute_id
product_id
当有人在寻找产品时,他们可以选择一个或多个属性。我遇到的问题是返回具有多个属性的单个产品。这应该是非常简单的我知道,但SQL真的不是我的事情,过去某一点我在逻辑上有点迷失。问题是我试图分别检查每个属性类,所以我想最终得到类似的东西:
SELECT DISTINCT products.product_id
FROM attribproducts
INNER JOIN products ON attribproducts.product_id = products.product_id
WHERE (attribproducts.attribute_id IN (9,10,11)
AND attribproducts.attribute_id IN (60,61))
我使用IN来分隔不同类别的属性块,因此我最终得到了某些类型的产品,但也有某些品牌的产品。从结果来看,似乎是导致问题的IN语句之间的AND。
任何人都可以帮忙吗?不幸的是,我没有完全重构数据库的奢侈品,它还有很多东西比这一点,所以任何建议如何使用我所拥有的将会感激不尽。
答案 0 :(得分:3)
查看问题SQL: Many-To-Many table AND query的答案。这是完全相同的问题。 Cletus给出了两个可能的解决方案,其中没有一个是非常微不足道的(但是再一次,根本没有简单的解决方案)。
答案 1 :(得分:1)
SELECT DISTINCT products.product_id
FROM products p
INNER JOIN attribproducts ptype on p.product_id = ptype.product_id
INNER JOIN attribproducts pbrand on p.product_id = pbrand.product_id
WHERE ptype.attribute_id IN (9,10,11)
AND pbrand.attribute_id IN (60,61)
答案 2 :(得分:0)
试试这个:
select * from products p, attribproducts a1, attribproducts a2
where p.product_id = a1.product_id
and p.product_id = a2.product_id
and a1.attribute_id in (9,10,11)
and a2.attribute_id in (60,61);
答案 3 :(得分:0)
这将不返回任何行,因为您只计算具有(9,10,11)AND(60,61)数字的行。
因为这些集合不相交,所以你不会得到任何行。
如果您使用OR,它将为产品提供属于集合9,10,11,60,61的属性,这不是您想要的,尽管您将获得多个行产品
您可以将该选择用作GROUP BY语句中的子查询,按产品数量进行分组,并按共享属性的数量对该分组进行排序。这将首先给你最高的匹配。
或者(如另一个答案所示),您可以为每个属性集添加表的新副本,仅为您提供与所有属性集匹配的产品。
答案 4 :(得分:0)
听起来你的数据架构对于存储而言非常好,但是选择/报告却很糟糕。当您拥有OBJECT,ATTRIBUTE,OBJECT-ATTRIBUTE和OBJECT-ATTRIBUTE-VALUE的数据结构时,您可以存储每个对象具有许多不同属性的许多对象。这有时被称为“垂直存储”。
但是,当您想要检索具有所有属性值的对象列表时,您必须进行可变数量的连接。在数据存储时,检索数据要容易得多(定义的数据列)
我已多次遇到这种情况。由于无法更改现有数据结构。我的建议是在顶部写一个“层”表。为您拥有的每个对象/产品动态创建一个表。然后在每个属性的新表中动态创建静态列。您需要将垂直存储的属性/值“展平”为静态列。从垂直架构转换为水平架构。
使用“flattened”表进行报告,并使用垂直表进行存储。
如果您需要示例代码或更多详细信息,请问我。
我希望这很清楚。我还没吃多少咖啡:)。
谢谢, - 马克
答案 5 :(得分:0)
您可以使用多个内部联接 - 我认为这样可行:
select distinct product_id
from products p
inner join attribproducts a1 on a1.product_id=p.product_id
inner join attribproducts a2 on a1.product_id=p.product_id
where a1.attribute_id in (9,10,11)
and a2.attribute_id in (60,61)