EAV-запросы и таблицы

Теперь у меня есть 4 таблицы:

table categories:
-id
-category

table products:
-id
-product
-price
-image

table attributes:
-id
-attribute
-product_id

table values:
-product_id
-attribute_id
-value

И я запрашиваю:

SELECT `id`, `product`, `price`, `image` FROM `products` WHERE `category_id` = $category->id

Теперь у меня есть массив продуктов для этой категории, и мне нужно получить его свойства: следующий запрос:

SELECT `products`.`id` AS `product_id`, 
`attributes`.`attribute`, 
`values`.`value` 
FROM `products` LEFT JOIN `attributes` ON (`attributes`.`product_id` = `products`.`id`) 
LEFT JOIN `values` ON (`values`.`product_id` = `products`.`id` 
AND `values`.`attribute_id` = `attributes`.`id`) 
WHERE `products`.`id` IN ($ids)

И он получает атрибуты со значениями, но меня интересует одно: возможно ли избавиться от столбца 'product_id' в table attributes и получить атрибуты и значения без этого столбца? Теперь это целая куча дублирующих атрибутов, например:

table attributes 
-id 1
-attribute Weight
-product_id 1

-id 2
-attribute Weight
-product_id 2

Пока я хочу просто:

-id 1
-attribute Weight

извините за мой английский, если какая-то часть моего сообщения нуждается в дополнительных пояснениях, пожалуйста, дайте мне сейчас


person nazarov    schedule 21.01.2012    source источник
comment
Вам не хватает category_id в описании вашей таблицы product.   -  person ypercubeᵀᴹ    schedule 21.01.2012
comment
Если оставить в стороне ограничения EAV, ваш дизайн предполагает, что разные продукты могут иметь разные разрешенные атрибуты (те, которые хранятся в таблице attribute). Если вам не нужна такая функциональность, вы можете использовать подход @vucetica.   -  person ypercubeᵀᴹ    schedule 21.01.2012


Ответы (1)


Это зависит от того, хотите ли вы, чтобы ваши атрибуты были специфичны для продукта, но вы, очевидно, этого не делаете. Кроме того, вам не нужен product_id в вашей таблице значений, если он есть в вашей таблице атрибутов. Таким образом, ваши таблицы имеют больше смысла, если они похожи на:

table categories:
-id
-category

table products:
-id
-product
-price
-image
-category_id

table attributes:
-id
-attribute
-product_id

table values:
-attribute_id
-value

На самом деле, я бы сделал EAV намного проще:

table categories:
-id
-category

table products:
-id
-product
-price
-image
-category_id

table attributes:
-id
-product_id
-attribute
-value

И тогда ваш запрос будет выглядеть так:

SELECT id, product, price, image, attribute, value
FROM products
    INNER JOIN attributes ON products.id = attributes.product_id
WHERE products.category_id = :category_id

Убедитесь, что у вас есть соответствующие индексы. Кроме того, то, как вы хотели сделать это, выбирая идентификаторы продуктов, а затем помещая их в IN, является плохой практикой.

person Aleksandar Vucetic    schedule 21.01.2012
comment
но если у меня есть, например, 10 атрибутов? - person nazarov; 21.01.2012
comment
он вернет 10 строк. ты этого не хочешь? - person Aleksandar Vucetic; 21.01.2012
comment
Это ограничит OP одной категорией для каждого продукта. Это наблюдение, а не критика. - person Mike Sherrill 'Cat Recall'; 21.01.2012
comment
Да, это еще одна вещь, которую можно улучшить и в оригинальном дизайне. - person Aleksandar Vucetic; 21.01.2012