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

时间:2009-06-29 12:04:51

标签: sql sql-server

我有一个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。

任何人都可以帮忙吗?不幸的是,我没有完全重构数据库的奢侈品,它还有很多东西比这一点,所以任何建议如何使用我所拥有的将会感激不尽。

6 个答案:

答案 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)