我有以下表结构:
产品(id,name,...)
+-----+------------+
| id | name |
+-----+------------+
| 1 | Product #1 |
| 2 | Product #2 |
| 3 | Product #3 |
| 4 | Product #4 |
+-----+------------+
属性(id,title,...)
+-----+------------+
| id | title |
+-----+------------+
| 1 | shape |
| 2 | colour |
| 3 | height |
| 4 | weight |
+-----+------------+
选项(id,title ...)
+-----+------------+
| id | title |
+-----+------------+
| 1 | round |
| 2 | square |
| 3 | oval |
| 4 | red |
| 5 | blue |
| 6 | green |
| 7 | tall |
| 8 | short |
| 9 | heavy |
| 10 | light |
+-----+------------+
和第四个(ProductAttribute - id,product_id,attribute_id,option_id),希望得到“所有又高又重的红色圆形产品”:
+-----+------------+--------------------+
| id | product | attribute | option |
+-----+------------+--------------------+
| 1 | Product #1 | shape | round |
| 2 | Product #2 | shape | oval |
| 3 | Product #3 | shape | round |
| 4 | Product #4 | shape | square |
| 5 | Product #1 | color | green |
| 6 | Product #2 | color | red |
| 7 | Product #3 | height | tall |
| 8 | Product #4 | height | short |
| 9 | Product #2 | weight | heavy |
| 10 | Product #1 | weight | light |
+-----+------------+--------------------+
我到目前为止还不是一个sql大师,也许我的想法无法奏效。
编辑:
Q1。问题是我该如何实现这一目标?例如,获得所有红色,高大,重型产品。
以下查询无法实现我的目的:
1:
SELECT ProductAttributes.product_id, ProductAttributes.id FROM ProductAttributes
WHERE (ProductAttributes.attribute_id = 1 AND ProductAttributes.option_id = 1)
AND (ProductAttributes.attribute_id = 3 AND ProductAttributes.option_id = 4);
2:
SELECT DISTINCT ProductAttributes.product_id, ProductAttributes.id FROM ProductAttributes
WHERE (ProductAttributes.attribute_id = 1 AND ProductAttributes.option_id = 1)
OR (ProductAttributes.attribute_id = 3 AND ProductAttributes.option_id = 4);
注意:我故意在我的查询中放入2个变量,因为真正的变量还有更多。
答案 0 :(得分:1)
键/值表是令人讨厌的。如果可以,请避免使用它们。那你就有这些表:
表格形状
+--------+ | shape | +--------+ | round | | oval | | round | | square | +--------+
表格颜色
+--------+ | color | +--------+ | green | | red | +--------+
表格高度
+--------+ | height | +--------+ | tall | | short | +--------+
表格权重
+--------+ | weight | +--------+ | heavy | | light | +--------+
表格产品
+-------------+--------------+--------+--------+--------+--------+ | product_no | product name | shape | color | height | weight | +-------------+--------------+--------+--------+--------+--------+ | 14214 | Product #1 | round | red | tall | heavy | | 22312 | Product #2 | oval | | short | heavy | | 35757 | Product #3 | square | green | tall | heavy | | 42468 | Product #4 | | red | short | light | +-------------+--------------+--------+--------+--------+--------+
查询
oraoledb12.dll
顺便说一下,你可以对ID做同样的事情。因此,所有查找表都将获得一个ID(round = 1,oval = 2,... green = 1,red = 2,...),并且product表将不再包含单词,而是ID。然后查询将是:
select *
from products
where shape = 'round'
and color = 'red'
and height = 'tall'
and weight = 'heavy';
答案 1 :(得分:1)
因此,您希望根据ProductAttribute表中的选项
进行选择在表中存储数据的更好方法是对第四列使用unique / id / primary key值,然后就可以了
SELECT * FROM ProductAttribute as attr
INNER JOIN Product as product ON product.id=attr.product_id
INNER JOIN Attribute as attr2 ON attr2.id=attr.attribute_id
WHERE attr.option=“round” OR attr.option=“red”
我希望这对你有所帮助!
答案 2 :(得分:1)
Fot键/值方法我使用复合键来提高一致性:
属性(attribute_no,title),PK = attribute_no
+--------------+------------+ | attribute_no | title | +--------------+------------+ | 1 | shape | | 2 | colour | | ... | ... | +--------------+------------+
attribute_option(attribute_no,option_no,value),PK = attribute_no,option_no
+--------------+-----------+------------+ | attribute_no | option_no | value | +--------------+-----------+------------+ | 1 | 1 | round | | 1 | 2 | square | | 2 | 1 | green | | 2 | 2 | red | | ... | ... | ... | +--------------+-----------+------------+
产品(product_no,product_name,...),PK = product_no
+------------+--------------+ | product_no | product_name | +------------+--------------+ | 7352871 | Product #1 | | 8956443 | Product #2 | | ... | ... | +------------+--------------+
product_attributes(product_no,attribute_no,option_no),PK = product_no,attribute_no
+------------+--------------+-----------+ | product_no | attribute_no | option_no | +------------+--------------+-----------+ | 7352871 | 1 | 1 | | 7352871 | 2 | 1 | | 8956443 | 1 | 2 | | 8956443 | 2 | 1 | +------------+--------------+-----------+
(你想在这个表的attribute_no + option_no上找一个索引。)
product_attributes
主键保证每个产品每个属性只获得一个值。嗯,这对于身高,体重等都有好处。但是,如果你想为产品提供多种颜色等,你需要这样的product_attributes
表,包括主键中的option_no
。对于唯一属性和多个属性,最终可能会有单独的表。也许以后你甚至想要推出具有可选和强制属性的产品组(冰箱有能量等级,T恤没有)。因此,这整个概念可能会增长,但上面的表格应该让您了解如何最好地解决这个问题。
查询所有高大而重的红色圆形产品:
select *
from product
where product_no in
(
select product_no
from product_attributes
where (attribute_no, option_no) =
(
select ao.attribute_no, ao.option_no
from attribute_option ao
join attribute a on a.attribute_no = ao.attribute_no
where a.title = 'colour'
and ao.value = 'red'
)
)
and product_no in
(
select product_no
from product_attributes
where (attribute_no, option_no) =
(
select ao.attribute_no, ao.option_no
from attribute_option ao
join attribute a on a.attribute_no = ao.attribute_no
where a.title = 'shape'
and ao.value = 'round'
)
)
and product_no in (...)
and product_no in (...);
或缩短聚合:
select *
from product
where product_no in
(
select pa.product_no
from product_attributes pa
join attribute a on a.attribute_no = pa.attribute_no
join attribute_option ao on a.attribute_no = pa.attribute_no
and a.option_no = pa.option_no
group by pa.product_no
having sum(a.title = 'colour' and ao.value = 'red') > 0
and sum(a.title = 'shape' and ao.value = 'round') > 0
and sum(a.title = 'height' and ao.value = 'tall') > 0
and sum(a.title = 'weight' and ao.value = 'heavy') > 0
)
答案 3 :(得分:0)
在网上搜索“mysql键值表”(感谢@Thorsten Kettner关键字,因为我缺乏术语),我最终得到的结果如下:
SELECT Product.id FROM Product
INNER JOIN ProductAttributes PA_1 ON
Product.id = PA_1.product_id
INNER JOIN ProductAttributes PA_2 ON
Product.id = PA_2.product_id
WHERE
(PA_1.attribute_id = 1 and PA_1.option_id = 1)
AND
(PA_2.attribute_id = 3 and PA_2.option_id = 4);
基本上,只要在查询中使用新属性,就需要不同的INNER JOIN
条件。
在“表现”方面会发生相当明显的打击。
根据this和this,不应使用键/值表进行过滤,但此时我别无选择,因此将由缓存服务器来保存当天
我的答案基于此(在我的情况下不需要GROUP BY
,因为我不使用聚合函数)Filtering and Grouping data from table with key/value pairs