【问题标题】:SQL searching product based on multiple criteria (if attribute='length' then value>70, if attribute='weight' then value>3)基于多个条件的 SQL 搜索产品(如果属性='长度'则值>70,如果属性='权重'则值>3)
【发布时间】:2021-04-15 15:21:59
【问题描述】:

我正在为大学做一个数据库项目。主题是建筑车间(锤子、锯子、螺丝刀等)。这样做的问题是我不能真正将所有东西都放在一个表“产品”中,因为它们具有不同的属性。于是问老师怎么设置,他推荐的就是这个。

我正在使用带有 SQL Anywhere 12 的 Sybase Central。这是我们正在使用的,由大学提供

称为产品的产品表

| Product_ID | Category | Manufacturer | Price | Amount in stock |

称为属性的属性表

| Attribute_ID | Attribute name |

两者的交集称为值

Product ID | Attribute ID | Value | Unit |

例如: 在产品表中,我有 3 把锤子

| Product_ID | Category | Manufacturer | Price | Amount in stock |

| 1          | hammer   | man1         | 20    | 17
| 2          | hammer   | man2         | 14    | 20
| 3          | hammer   | man3         | 7    | 30

在属性表中:

| Attribute_ID | Attribute name |
| 1            | length         |
| 2            | weight         |

价值

| Product ID | Attribute ID | Value | Unit |
| 1          | 1            | 90    | cm   |
| 1          | 2            | 1     | kg   |
| 2          | 1            | 100   | cm   |
| 2          | 2            | 4     | kg   |
| 3          | 1            | 50    | cm   |
| 3          | 2            | 3     | kg   |

然后我使用连接来获取信息,就像这样

SELECT product.product_id,
       product.category,
       product.manufacturer,
       product.price,
       product.amount_in_stock,
       attribute.name,
       value.value,
       value.unit
FROM product
INNER JOIN value ON product.product_id=value.value_id
INNER JOIN attribute ON attribute.attribute_id=value.attribute_id

按一个条件搜索很简单,我可以在哪里添加一个。因此,如果我想要长度超过 80 厘米的锤子,我只需添加

WHERE product.category='hammer' AND attribute.name ='length' AND value.value>80

这会显示锤子 1 和 2。

到目前为止,一切都很好,但是当我尝试按多个条件进行搜索时出现了问题。因此,例如长度超过 80 且重量超过 2 的锤子。在上面的示例中,这只是锤子 2。添加 OR 或 UNION 不起作用,因为它会显示长度超过 80 厘米的锤子列表,并且重量超过 2 公斤的锤子列表,不是同时的。如果我像这样添加或

WHERE (product.category='hammer' AND attribute.name ='length' AND value.value>80)
OR ((product.category='hammer' AND attribute.name ='weight' AND value.value>2)

它将显示锤子 2 和 3,而不仅仅是锤子 2。

我试过做一些像这样的奇怪案例

WHERE
CASE
   WHEN (CASE WHEN (attribute.name='length' THEN 1 ELSE 0)) IS NOT NULL THEN value.value>80)
   WHEN (CASE WHEN (attribute.name='weight' THEN 1 ELSE 0)) IS NOT NULL THEN value.value>2)
END

如果属性是长度,嵌套的 CASE 将返回 1,然后它会检查值是否>80 如果属性不长,则 in 将返回 0 并且什么也不做,但它不起作用。

我也尝试过嵌套SELECT,但似乎INNER JOIN在嵌套select中不起作用或者我不知道该怎么写。

SELECT product.product_id
FROM (
       SELECT product.product_id,
             product.category,
             product.manufacturer,
             product.price,
             product.amount_in_stock,
             attribute.name,
             value.value,
             value.unit
      FROM product
      INNER JOIN value ON product.product_id=value.value_id
      INNER JOIN attribute ON attribute.attribute_id=value.attribute_id
      WHERE product.category='hammer' AND attribute.name ='length' AND value.value>80
)
WHERE attribute.name='weight' and value.value>2

有没有这样的写法

IF (attribute.name='length' THEN value>80)
IF (attribute.name='weight' THEN value>2)

我也不能问我的老师,因为他是数据库理论的,不是SQL的,我必须交给项目的SQL老师不好,也不会帮忙。列名称或代码中也可能存在小错别字,因为我必须将名称翻译成英文。所以如果有的话,他们不是问题

TL;DR

SELECT 语句将显示长度超过 80 厘米且重量超过 2 公斤的锤子。所以,在上面的例子中,只有锤子 2。锤子 1 的长度超过 80 厘米,锤子 3 的重量超过 2 公斤,但只有锤子 2 是同时的。

【问题讨论】:

    标签: sql if-statement select search conditional-statements


    【解决方案1】:

    我建议聚合。你还没有指定数据库,但是让我们给你一个例子,只是返回product_id

    SELECT p.product_id
    FROM product p JOIN
         value v
         ON p.product_id = v.value_id JOIN
         attribute a
         ON a.attribute_id = v.attribute_id
    WHERE p.category = 'hammer'   -- filter before the aggregation on this
    GROUP BY p.product_id
    HAVING SUM(CASE WHEN a.name = 'length' and v.value > 80 THEN 1 ELSE 0 END) A> 0 ND
           SUM(CASE WHEN a.name = 'weight' and v.value > 2 THEN 1 ELSE 0 END) > 0;  
    

    您可以引入最终结果所需的其他属性。

    请注意,这假定value 是一个数字。否则,您可能会遇到类型转换错误或错误的字符串比较。

    【讨论】:

    • 好的,我搞定了。我只需要在每个 SUM 之后添加 >0
    • @qwardes 。 . .是的,在大多数数据库中都是如此——这就是我的意图。我确定了答案。
    猜你喜欢
    • 2021-04-18
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-17
    • 2019-08-19
    • 1970-01-01
    相关资源
    最近更新 更多