[英]What is the best way to implement this SQL query?
我有一个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导致了问题。
有人可以帮忙吗? 不幸的是,我没有完全重构数据库的奢侈,除此以外,它还有很多其他功能,因此,将不胜感激地接受任何有关如何使用我所拥有的建议。
看一下问题SQL:多对多表AND查询的答案。 这是完全相同的问题。 Cletus提供了2种可能的解决方案,但都不是很琐碎的(但是再说一次,根本就没有琐碎的解决方案)。
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)
尝试这个:
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);
这将不返回任何行,因为您只计算具有(9、10、11)和(60、61)的数字的行。
因为这些集合不相交,所以您将不会获得任何行。
如果改用OR,它将为产品提供9、10、11、60、61集的属性,这也不是您想要的,尽管您随后将为每个产品获得多行。
您可以将该select用作GROUP BY语句中的子查询,根据产品数量进行分组,并根据共享属性的数量对分组进行排序。 那将首先给您最高的比赛。
另外(如另一个答案所示),您可以为每个属性集加入表的新副本,从而仅给您匹配所有属性集的那些产品。
听起来您有一个很好的数据模式,可以存储,但是选择/报告时却很糟糕。 当您具有OBJECT,ATTRIBUTE,OBJECT-ATTRIBUTE和OBJECT-ATTRIBUTE-VALUE的数据结构时,可以存储许多对象,每个对象具有许多不同的属性。 有时称为“垂直存储”。
但是,当您要检索具有所有属性值的对象列表时,必须进行可变数量的联接。 水平存储时检索数据要容易得多(定义的数据列)
我已经多次遇到这种情况。 由于您无法更改现有数据结构。 我的建议是在表的顶部写一个“层”。 为您拥有的每个对象/产品动态创建一个表。 然后在这些新表中为每个属性动态创建静态列。 您几乎需要将垂直存储的属性/值“展平”到静态列中。 从垂直架构转换为水平架构。
使用“展平”表进行报告,并使用垂直表进行存储。
如果您需要示例代码或更详细的信息,请问我。
我希望这很清楚。 我还没喝咖啡:)
谢谢-马克
您可以使用多个内部联接-我认为这可以工作:
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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.