Variantes de modelado de productos

He estado tratando de modelar variantes de productos y pensé que podría necesitar usar EAV. Podría haberlo hecho sin EAV, pero me preocupa que me haya perdido algo. Aquí está mi diseño:

Esto es lo que estoy tratando de representar:

A product puede tener 0 o másproduct variants (por ejemplo, un producto de camiseta puede tener variantes de tamaño y color).A product variant puede tener 1 o másproduct variant options (por ejemplo, la variante de tamaño puede ser pequeña, mediana, grande).UnSKU está compuesto por 1 o másproduct variant options (elproduct_variant_option_combination La tabla contendría todas las combinaciones posibles de `product_variant_options. Entonces, si hubiera 3 tamaños y 3 colores, habría 3 * 3 = 9 combinaciones, y cada combinación recibiría su propia SKU y precio).A product puede tener 1 o másSKUs.

Si el producto no tiene ninguna variante, simplemente ignoreproduct_variants, product_variant_optionsyproduct_variant_option_combinations.

¿Es este diseño de sonido? ¿Terminaré teniendo problemas para consultar esto? ¿Escalará? ¿Está normalizado?

ACTUALIZACIÓN 1

@ Edper:

Si un producto puede tener 0 o muchas variantes de producto (modo opcional) (por ejemplo, tamaño, color, etc.). ¿Se deduce que las variantes de un producto también pueden tener 0 o muchos productos que tengan esa variante?

No lo creo. Es posible que un producto como una "camiseta" pueda tener una variante de "talla" y otro producto como "pantalones" también puede tener una variante de "talla", pero creo que eso es solo una casualidad. No es necesario hacer que el "tamaño" solo aparezca como un registro porque el "tamaño" puede tener un contexto diferente.

Los productos con los que estoy tratando varían mucho y están obligados a tener variantes con nombres similares.

ACTUALIZACIÓN 2:

Aquí hay un ejemplo de cómo veo mis datos:

He encajonado la varianteSize y sus valores asociados. Quiero dejar en claro que estos no se consideran datos duplicados. losSize La variante para los 3 productos es solo una casualidad. No hay necesidad de normalizar esto, creo. Cada producto puede tener 0 o más variantes, y son desconocidas para mí. Espero "duplicados" (aunque en realidad no son duplicados, ya que siempre están en el contexto de un producto en particular, por lo tanto, la variante "Tamaño" del Widget 1 no es lo mismo que la variante "Tamaño" del Widget 2).

ACTUALIZACIÓN 3:

Ahora veo que, en mi diseño, es posible queproduct tener múltiples idénticosproduct_variants. Creo que eso se puede resolver haciendoproduct_variants.product_id yproduct_variants.name Una clave compuesta. Esto significa que el widget 1 solo puede tener la variante "Tamaño" una vez.

product_variant_options.product_variant_id product_variant_options.name También necesitaría ser una clave compuesta.

ACTUALIZACIÓN 4:

Al actualizar miproduct_variant_option_combinations para incluirproduct_variant_id (FK aproduct_variants.id) y aplicar una restricción ÚNICA conproduct_variant_option_combinations.sku_id yproduct_variant_option_combinations.product_variant_id, Creo que pude evitar el problema de tener un SKU que es "Pequeño" y "Grande". ¿Es esto correcto?

-- 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 @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@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 CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

Respuestas a la pregunta(1)

Su respuesta a la pregunta