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:
Aproduct
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_options
yproduct_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 */;