Я пытался моделировать варианты продукта и думал, что мне может понадобиться использовать EAV. Я мог бы сделать это без EAV, но я обеспокоен тем, что мог что-то пропустить. Здесь моя конструкция:
Вот что я пытаюсь представить:
- A
product
может иметь 0 или болееproduct variants
(например, продукт футболки может иметь размер и цветные варианты). - A
product variant
может иметь 1 или болееproduct variant options
(например, вариант размера может быть небольшим, средним, большим). - А
SKU
состоит из 1 или болееproduct variant options
(таблицаproduct_variant_option_combination
содержит все возможные комбинации `product_variant_options. Итак, если бы было 3 размера и 3 цвета, было бы 3 * 3 = 9 комбинаций - и каждая комбинация получит собственный SKU и цену). - A
product
может иметь 1 или болееSKUs
.
Если у продукта нет вариантов, просто игнорируйте product_variants
, product_variant_options
и product_variant_option_combinations
.
Является ли этот дизайн звуком? У меня возникнут проблемы с запросом? Будет ли оно масштабироваться? Нормализовано?
ОБНОВЛЕНИЕ 1
@Edper:
Если продукт может иметь 0 или много (опционный режим) варианты продукта (например, размер, цвет и т.д.). Из этого следует, что варианты продукта могут также иметь 0 или много продуктов, имеющих этот вариант?
Я так не думаю. Возможно, что у продукта, такого как "футболка", может быть вариант "размер" , а другой продукт, такой как "штаны", также может иметь "размерный" вариант, но я думаю, что это всего лишь случайность. Нет необходимости делать "размер" только как одну запись, потому что "размер" может иметь другой контекст.
Продукты, с которыми я имею дело, сильно различаются, и они должны иметь похожие варианты.
ОБНОВЛЕНИЕ 2:
Вот пример того, как я вижу свои данные:
Я применил вариант Size
и связанные с ним значения. Я хочу дать понять, что они не считаются дублирующимися данными. Вариант Size
для трех продуктов - это просто случайность. Думаю, нет необходимости нормализовать это. Каждый продукт может иметь 0 или более вариантов - и они мне неизвестны. Я ожидаю "дубликатов" (хотя они на самом деле не дублируются, поскольку они всегда относятся к определенному продукту, поэтому вариант "Размер" виджета "1" отличается от варианта "Размер" Widget 2).
ОБНОВЛЕНИЕ 3:
Теперь я вижу, что в моем дизайне возможно, что product
имеет несколько идентичных product_variants
. Я думаю, что это можно решить, сделав product_variants
. product_id
и product_variants
. name
составной ключ. Это означает, что Widget 1 может иметь только вариант "Размер" .
product_variant_options
. product_variant_id
product_variant_options
. name
также должен быть составным.
ОБНОВЛЕНИЕ 4:
Обновив мой product_variant_option_combinations
, включите product_variant_id
(FK в product_variants
. id
) и соблюдая ограничение UNIQUE с помощью product_variant_option_combinations
. sku_id
и product_variant_option_combinations
. product_variant_id
, я думаю, что я смог предотвратить проблему наличия SKU, который является как "Малым", так и "Большим". Это правильно?
-- phpMyAdmin SQL Dump
-- version 4.1.14
-- http://www.phpmyadmin.net
--
-- Host: 127.0.0.1
-- Generation Time: Jul 30, 2014 at 03:35 AM
-- Server version: 5.6.17
-- PHP Version: 5.5.12
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
/*!40101 SET @[email protected]@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
--
-- Database: `mydb`
--
-- --------------------------------------------------------
--
-- Table structure for table `products`
--
CREATE TABLE IF NOT EXISTS `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- Dumping data for table `products`
--
INSERT INTO `products` (`id`, `name`) VALUES
(1, 'Widget 1');
-- --------------------------------------------------------
--
-- Table structure for table `product_variants`
--
CREATE TABLE IF NOT EXISTS `product_variants` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_product_id_name` (`product_id`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- Dumping data for table `product_variants`
--
INSERT INTO `product_variants` (`id`, `product_id`, `name`) VALUES
(2, 1, 'Color'),
(1, 1, 'Size');
-- --------------------------------------------------------
--
-- Table structure for table `product_variant_options`
--
CREATE TABLE IF NOT EXISTS `product_variant_options` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_variant_id` int(11) NOT NULL,
`name` varchar(45) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_product_variant_id_name` (`product_variant_id`,`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Dumping data for table `product_variant_options`
--
INSERT INTO `product_variant_options` (`id`, `product_variant_id`, `name`) VALUES
(2, 1, 'Large'),
(1, 1, 'Small'),
(4, 2, 'Black'),
(3, 2, 'White');
-- --------------------------------------------------------
--
-- Table structure for table `skus`
--
CREATE TABLE IF NOT EXISTS `skus` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`sku` varchar(45) NOT NULL,
`price` decimal(10,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `skus_product_id_products_id_idx` (`product_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;
--
-- Dumping data for table `skus`
--
INSERT INTO `skus` (`id`, `product_id`, `sku`, `price`) VALUES
(1, 1, 'W1SSCW', '10.00'),
(2, 1, 'W1SSCB', '10.00'),
(3, 1, 'W1SLCW', '12.00'),
(4, 1, 'W1SLCB', '15.00');
-- --------------------------------------------------------
--
-- Table structure for table `skus_product_variant_options`
--
CREATE TABLE IF NOT EXISTS `skus_product_variant_options` (
`sku_id` int(11) NOT NULL,
`product_variant_id` int(11) NOT NULL,
`product_variant_options_id` int(11) NOT NULL,
PRIMARY KEY (`sku_id`,`product_variant_options_id`,`product_variant_id`),
UNIQUE KEY `UNIQUE_sku_id_product_variant_id` (`sku_id`,`product_variant_id`),
KEY `spvo_product_variant_options_id_pro_idx` (`product_variant_options_id`),
KEY `spvo_product_variant_id_product_var_idx` (`product_variant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `skus_product_variant_options`
--
INSERT INTO `skus_product_variant_options` (`sku_id`, `product_variant_id`, `product_variant_options_id`) VALUES
(1, 1, 1),
(2, 1, 1),
(3, 1, 2),
(4, 1, 2),
(1, 2, 3),
(3, 2, 3),
(2, 2, 4),
(4, 2, 4);
--
-- Constraints for dumped tables
--
--
-- Constraints for table `product_variants`
--
ALTER TABLE `product_variants`
ADD CONSTRAINT `product_variants_product_id_products_id` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
--
-- Constraints for table `product_variant_options`
--
ALTER TABLE `product_variant_options`
ADD CONSTRAINT `product_variant_options_product_variant_id_product_variants_id` FOREIGN KEY (`product_variant_id`) REFERENCES `product_variants` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
--
-- Constraints for table `skus`
--
ALTER TABLE `skus`
ADD CONSTRAINT `skus_product_id_products_id` FOREIGN KEY (`product_id`) REFERENCES `products` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
--
-- Constraints for table `skus_product_variant_options`
--
ALTER TABLE `skus_product_variant_options`
ADD CONSTRAINT `skus_product_variant_options_sku_id_skus_id` FOREIGN KEY (`sku_id`) REFERENCES `skus` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT `spvo_product_variant_options_id_product_variant_options_id` FOREIGN KEY (`product_variant_options_id`) REFERENCES `product_variant_options` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT `spvo_product_variant_id_product_variants_id` FOREIGN KEY (`product_variant_id`) REFERENCES `product_variants` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION;
/*!40101 SET [email protected]_CHARACTER_SET_CLIENT */;
/*!40101 SET [email protected]_CHARACTER_SET_RESULTS */;
/*!40101 SET [email protected]_COLLATION_CONNECTION */;