繁体   English   中英

实现此SQL查询的最佳方法是什么?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM