diff --git a/.gitignore b/.gitignore index 1275d8b..3bb08a8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules db.json db.*.json schema.*.json +*.csv diff --git a/README.md b/README.md index ca414e1..7af03fe 100644 --- a/README.md +++ b/README.md @@ -16,32 +16,44 @@ sys 0m0.983s node schema.js ``` -## Product Types +## Database Overview + +### Product Types ```bash jq '.[].name' db.json ``` -## Product Brands +### Product Brands ```bash jq '.[0].products[].name' db.json ``` -## Product Series +### Product Series ```bash jq '.[0].products[0].subproducts[].name' db.json ``` -## Products +### Products ```bash jq '.[0].products[0].subproducts[0].skus[]."Product Name"' db.json ``` -## Specification Categories +### Specification Categories ```bash jq '.[0].products[0].subproducts[0].skus[0].specs | keys' db.json ``` + +## Data Loading + +```bash +\copy ProductTypes FROM 'ProductTypes.csv' DELIMITER ',' CSV HEADER ENCODING 'UTF8'; +\copy ProductBrands FROM 'ProductBrands.csv' DELIMITER ',' CSV HEADER ENCODING 'UTF8'; +\copy ProductSeries FROM 'ProductSeries.csv' DELIMITER ',' CSV HEADER ENCODING 'UTF8'; +\copy Products FROM 'Products.csv' DELIMITER ',' CSV HEADER ENCODING 'UTF8'; +\copy ProductsSpecifications FROM 'ProductsSpecifications.csv' DELIMITER ',' CSV HEADER ENCODING 'UTF8'; +``` \ No newline at end of file diff --git a/csv.sh b/csv.sh new file mode 100644 index 0000000..dc52391 --- /dev/null +++ b/csv.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# This script reads a db.json file, and convert it into a series of CSV files: +# ProductTypes.csv +# ProductBrands.csv +# ProductSeries.csv +# Products.csv +# ProductsSpecifications.csv + +PRODUCT_TYPES=$(jq '.[].name' db.json | tr -d '"') +PRODUCT_TYPE_ID=1 +rm -fr ProductTypes.csv +rm -fr ProductBrands.csv +rm -fr ProductSeries.csv +rm -fr Products.csv + +echo "Id,Name" >> ProductTypes.csv +echo "ProductType,Id,Name" >> ProductBrands.csv +echo "ProductType,ProductBrand,Id,Name,Url" >> ProductSeries.csv +echo "ProductType,ProductBrand,ProductSerie,Id,Name,Url" >> Products.csv + +while IFS= read -r PRODUCT_TYPE ; do + echo "$PRODUCT_TYPE_ID,$PRODUCT_TYPE" >> ProductTypes.csv + + PRODUCT_BRANDS=$(jq \ + --arg product_type "$(echo "$PRODUCT_TYPE")" \ + '.[] | select(.name == $product_type) | .products[].name' db.json | tr -d '"') + PRODUCT_BRAND_ID=1 + + while IFS= read -r PRODUCT_BRAND ; do + echo "$PRODUCT_TYPE_ID,$PRODUCT_BRAND_ID,$PRODUCT_BRAND" >> ProductBrands.csv + + PRODUCT_SERIES=$(jq \ + --arg product_type "$(echo "$PRODUCT_TYPE")" \ + --arg product_brand "$(echo "$PRODUCT_BRAND")" \ + '.[] | select(.name == $product_type) | .products[] | select(.name == $product_brand) | .subproducts[].name' db.json | tr -d '"') + PRODUCT_SERIE_ID=1 + + while IFS= read -r PRODUCT_SERIE ; do + PRODUCT_SERIE_URL=$(jq \ + --arg product_serie "$(echo "$PRODUCT_SERIE")" \ + '.[].products[].subproducts[] | select(.name == $product_serie) | .href' db.json | tr -d '"') + PRODUCT_SERIE=$(echo "$PRODUCT_SERIE" | tr -d '\r') + echo "$PRODUCT_TYPE_ID,$PRODUCT_BRAND_ID,$PRODUCT_SERIE_ID,$PRODUCT_SERIE,$PRODUCT_SERIE_URL" >> ProductSeries.csv + + PRODUCTS=$(jq \ + --arg product_type "$(echo "$PRODUCT_TYPE")" \ + --arg product_brand "$(echo "$PRODUCT_BRAND")" \ + --arg product_serie "$(echo "$PRODUCT_SERIE")" \ + '.[] | select(.name == $product_type) | .products[] | select(.name == $product_brand) | .subproducts[] | select(.name == $product_serie) | .skus[]."Product Name"' db.json | tr -d '"') + PRODUCT_ID=1 + + while IFS= read -r PRODUCT ; do + PRODUCT_URL=$(jq \ + --arg product "$(echo "$PRODUCT")" \ + '.[].products[].subproducts[].skus[] | select(."Product Name" == $product) | .Url' db.json | tr -d '"') + PRODUCT=$(echo "$PRODUCT" | tr -d '\r') + echo "$PRODUCT_TYPE_ID,$PRODUCT_BRAND_ID,$PRODUCT_SERIE_ID,$PRODUCT_ID,$PRODUCT,$PRODUCT_URL" >> Products.csv + PRODUCT_ID=$((PRODUCT_ID + 1)) + done <<< "$PRODUCTS" + PRODUCT_SERIE_ID=$((PRODUCT_SERIE_ID + 1)) + done <<< "$PRODUCT_SERIES" + PRODUCT_BRAND_ID=$((PRODUCT_BRAND_ID + 1)) + done <<< "$PRODUCT_BRANDS" + PRODUCT_TYPE_ID=$((PRODUCT_TYPE_ID + 1)) +done <<< "$PRODUCT_TYPES" + +echo "ProductType,ProductBrand,ProductSerie,ProductId,Specification,Value" >> ProductsSpecifications.csv +sed 1d Products.csv | while IFS= read -r LINE; do + PRODUCT_TYPE=$(echo $LINE | awk -F, '{print $1}') + PRODUCT_BRAND=$(echo $LINE | awk -F, '{print $2}') + PRODUCT_SERIE=$(echo $LINE | awk -F, '{print $3}') + PRODUCT_ID=$(echo $LINE | awk -F, '{print $4}') + PRODUCT_NAME=$(echo $LINE | awk -F, '{print $5}') + + jq \ + --arg product "$(echo "$PRODUCT_NAME")" \ + '.[].products[].subproducts[].skus[] | select(."Product Name" == $product) | .specs | [leaf_paths as $path | {"key": $path | join("."), "value": getpath($path)}] | (map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $rows[] | @csv'\ + db.json | sed -e "s/^/${PRODUCT_TYPE},${PRODUCT_BRAND},${PRODUCT_SERIE},${PRODUCT_ID},/" >> ProductsSpecifications.csv +done \ No newline at end of file diff --git a/query.sql b/query.sql new file mode 100644 index 0000000..612f727 --- /dev/null +++ b/query.sql @@ -0,0 +1,431 @@ +-- 1. Which is the latest Intel Core Processor released? + +select IntelCoreProducts.Name, IntelCoreProducts.Url, LatestProducts.Value as "Launch Date" +from ( + select ProductType, ProductBrand, ProductSerie, Id, Name, Url + from Products + where (ProductType, ProductBrand) in ( + select ProductType, Id as ProductBrand + from ProductBrands + where name = 'Intel® Core™ Processors' + ) +) IntelCoreProducts +join ( + select * + from ProductsSpecifications + where Specification = 'Supplemental Information.Launch Date' + and Value = ( + select Value as "Max Launch Date" + from ProductsSpecifications + where (ProductType, ProductBrand, ProductSerie, ProductId) in ( + select ProductType, ProductBrand, ProductSerie, Id as ProductId + from Products + where (ProductType, ProductBrand) in ( + select ProductType, Id as ProductBrand + from ProductBrands + where name = 'Intel® Core™ Processors' + ) + ) + and Specification = 'Supplemental Information.Launch Date' + order by substring(Value from 4 for 2) desc, substring(Value from 2 for 1) desc + limit 1 + ) +) LatestProducts +on IntelCoreProducts.ProductType = LatestProducts.ProductType +and IntelCoreProducts.ProductBrand = LatestProducts.ProductBrand +and IntelCoreProducts.ProductSerie = LatestProducts.ProductSerie +and IntelCoreProducts.Id = LatestProducts.ProductId + +-- 2. Which is the latest Intel Xeon Processor released? + +select IntelXeonProducts.Name, IntelXeonProducts.Url, LatestProducts.Value as "Launch Date" +from ( + select ProductType, ProductBrand, ProductSerie, Id, Name, Url + from Products + where (ProductType, ProductBrand) in ( + select ProductType, Id as ProductBrand + from ProductBrands + where name = 'Intel® Xeon® Processors' + ) +) IntelXeonProducts +join ( + select * + from ProductsSpecifications + where Specification = 'Supplemental Information.Launch Date' + and Value = ( + select Value as "Max Launch Date" + from ProductsSpecifications + where (ProductType, ProductBrand, ProductSerie, ProductId) in ( + select ProductType, ProductBrand, ProductSerie, Id as ProductId + from Products + where (ProductType, ProductBrand) in ( + select ProductType, Id as ProductBrand + from ProductBrands + where name = 'Intel® Xeon® Processors' + ) + ) + and Specification = 'Supplemental Information.Launch Date' + order by substring(Value from 4 for 2) desc, substring(Value from 2 for 1) desc + limit 1 + ) +) LatestProducts +on IntelXeonProducts.ProductType = LatestProducts.ProductType +and IntelXeonProducts.ProductBrand = LatestProducts.ProductBrand +and IntelXeonProducts.ProductSerie = LatestProducts.ProductSerie +and IntelXeonProducts.Id = LatestProducts.ProductId; + +-- 3. Which processors works with a Thermal Design Power between 95 and 105 W? + +select Name, Url +from Products +where (ProductType, ProductBrand, ProductSerie, Id) in ( + select ProductType, ProductBrand, ProductSerie, ProductId as Id + from ProductsSpecifications + where Specification = 'CPU Specifications.TDP' + and left(Value, -2)::numeric >= 95 + and left(Value, -2)::numeric <= 105 +); + +-- 4. Which processors were launched in 2021? + +select Name, Url +from Products +join ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Supplemental Information.Launch Date' + and substring(Value from 4 for 2) = '21' +) ProductsLaunchedIn2021 +on Products.ProductType = ProductsLaunchedIn2021.ProductType +and Products.ProductBrand = ProductsLaunchedIn2021.ProductBrand +and Products.ProductSerie = ProductsLaunchedIn2021.ProductSerie +and Products.Id = ProductsLaunchedIn2021.ProductId +where Products.ProductType = ( + select Id + from ProductTypes + where name = 'Processors' +); + +-- 5. Which is the processor with the maximum base frequency available? + +select Name, Url +from Products +join ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where ProductType = ( + select Id + from ProductTypes + where Name = 'Processors' + ) + and Specification = 'CPU Specifications.Processor Base Frequency' + and right(Value, 3) = 'GHz' + and left(Value, -4)::numeric = ( + select max(left(Value, -4)::numeric) as "Max Processor Base Frequency" + from ProductsSpecifications + where ProductType = ( + select Id + from ProductTypes + where Name = 'Processors' + ) + and Specification = 'CPU Specifications.Processor Base Frequency' + and right(Value, 3) = 'GHz' + ) +) ProcessorsWithMaxBaseFrequency +on Products.ProductType = ProcessorsWithMaxBaseFrequency.ProductType +and Products.ProductBrand = ProcessorsWithMaxBaseFrequency.ProductBrand +and Products.ProductSerie = ProcessorsWithMaxBaseFrequency.ProductSerie +and Products.Id = ProcessorsWithMaxBaseFrequency.ProductId; + +-- 6. Which processor generation was available in 2018? + +select Name, Url +from ProductSeries +join ( + select ProductType, ProductBrand, ProductSerie + from ProductsSpecifications + where Specification = 'Supplemental Information.Launch Date' + and substring(Value from 4 for 2) = '18' + and (ProductType, ProductBrand) = ( + select ProductType, Id as ProductBrand + from ProductBrands + where name = 'Intel® Core™ Processors' + ) +) IntelCoreProcessorsLaunchedIn2018 +on ProductSeries.ProductType = IntelCoreProcessorsLaunchedIn2018.ProductType +and ProductSeries.ProductBrand = IntelCoreProcessorsLaunchedIn2018.ProductBrand +and ProductSeries.Id = IntelCoreProcessorsLaunchedIn2018.ProductSerie +group by Name, Url + +-- 7. Which is the most inexpensive NUC mini-PC? + +select Name, Url +from Products +join ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Essentials.Recommended Customer Price' + and split_part(split_part(Value, ' ', 1), '$', 2)::numeric = ( + select min("Min Price") + from ( + select split_part(split_part(Value, ' ', 1), '$', 2)::numeric as "Min Price" + from ProductsSpecifications + where Specification = 'Essentials.Recommended Customer Price' + and ProductType = ( + select Id + from ProductTypes + where Name = 'Intel® NUC' + ) + ) IntelNucMinPrices + ) + and ProductType = ( + select Id + from ProductTypes + where Name = 'Intel® NUC' + ) +) MinPriceIntelNuc +on Products.ProductType = MinPriceIntelNuc.ProductType +and Products.ProductBrand = MinPriceIntelNuc.ProductBrand +and Products.ProductSerie = MinPriceIntelNuc.ProductSerie +and Products.Id = MinPriceIntelNuc.ProductId + +-- 8. Which is the most expensive NUC mini-PC? + +select Name, Url +from Products +join ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Essentials.Recommended Customer Price' + and split_part(split_part(Value, ' ', 1), '$', 2)::numeric = ( + select max("Max Price") + from ( + select split_part(split_part(Value, ' ', 1), '$', 2)::numeric as "Max Price" + from ProductsSpecifications + where Specification = 'Essentials.Recommended Customer Price' + and ProductType = ( + select Id + from ProductTypes + where Name = 'Intel® NUC' + ) + ) IntelNucMaxPrices + ) + and ProductType = ( + select Id + from ProductTypes + where Name = 'Intel® NUC' + ) +) MinPriceIntelNuc +on Products.ProductType = MinPriceIntelNuc.ProductType +and Products.ProductBrand = MinPriceIntelNuc.ProductBrand +and Products.ProductSerie = MinPriceIntelNuc.ProductSerie +and Products.Id = MinPriceIntelNuc.ProductId + +-- 9. Which are the vPro enabled platforms in the 11th generation of Core products? + +select Name, Url +from Products +join ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Advanced Technologies.Intel vPro® Platform Eligibility ‡' + and Value = 'Yes' + and (ProductType, ProductBrand, ProductSerie) in ( + select ProductType, ProductBrand, Id as ProductSerie + from ProductSeries + where Name like '%' || '11th Generation Intel® Core™' || '%' + ) +) IntelVProEnabledProducts +on Products.ProductType = IntelVProEnabledProducts.ProductType +and Products.ProductBrand = IntelVProEnabledProducts.ProductBrand +and Products.ProductSerie = IntelVProEnabledProducts.ProductSerie +and Products.Id = IntelVProEnabledProducts.ProductId; + +-- 10. Which are the different Intel FPGA platforms? + +select Name, Url +from Products +where ProductType = ( + select Id + from ProductTypes + where Name = 'Intel® FPGAs' +); + +-- 11. Which is the latest available Intel IPU platforms? + +select Name, Url +from Products +join ( + select distinct ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where value like '%' || 'IPU' || '%' +) IntelProductsWithIPU +on Products.ProductType = IntelProductsWithIPU.ProductType +and Products.ProductBrand = IntelProductsWithIPU.ProductBrand +and Products.ProductSerie = IntelProductsWithIPU.ProductSerie +and Products.Id = IntelProductsWithIPU.ProductId; + +-- 12. Which is the average price of a Intel Core CPU by Generation? + +select Name, Url, "Avg Price" +from ProductSeries +join ( + select ProductType, ProductBrand, ProductSerie, + trunc(avg(split_part(split_part(Value, ' ', 1), '$', 2)::numeric), 2)::money as "Avg Price" + from ProductsSpecifications + where (ProductType, ProductBrand) in ( + select ProductType, Id as ProductBrand + from ProductBrands + where Name = 'Intel® Core™ Processors' + ) + and Specification = 'Essentials.Recommended Customer Price' + group by ProductType, ProductBrand, ProductSerie +) ProductSeriesAvgPrices +on ProductSeries.ProductType = ProductSeriesAvgPrices.ProductType +and ProductSeries.ProductBrand = ProductSeriesAvgPrices.ProductBrand +and ProductSeries.Id = ProductSeriesAvgPrices.ProductSerie; + +-- 13. Which platforms have more than 20 Cores and a Frequency Grater Than 4.5 GHz? + +select Products.Name, Products.Url +from Products +join ( + ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'CPU Specifications.Total Cores' + and Value::numeric > 20 + ) + INTERSECT + ( + select ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'CPU Specifications.Processor Base Frequency' + and right(Value, 3) = 'GHz' + and left(Value, -4)::numeric >= 4.5 + ) +) ProductsWithMoreThan20CoresAndMoreThan45Ghz +on Products.ProductType = ProductsWithMoreThan20CoresAndMoreThan45Ghz.ProductType +and Products.ProductBrand = ProductsWithMoreThan20CoresAndMoreThan45Ghz.ProductBrand +and Products.ProductSerie = ProductsWithMoreThan20CoresAndMoreThan45Ghz.ProductSerie +and Products.Id = ProductsWithMoreThan20CoresAndMoreThan45Ghz.ProductId; + +-- 14. Which platforms supports Intel Boot Guard? + +select Name, Url +from Products +join ( + select distinct ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Security & Reliability.Intel® Boot Guard' + and Value = 'Yes' +) IntelProductsWithIntelBootGuard +on Products.ProductType = IntelProductsWithIntelBootGuard.ProductType +and Products.ProductBrand = IntelProductsWithIntelBootGuard.ProductBrand +and Products.ProductSerie = IntelProductsWithIntelBootGuard.ProductSerie +and Products.Id = IntelProductsWithIntelBootGuard.ProductId; + +-- 15. Which platforms supports Intel Remote Platform Erase? + +select Name, Url +from Products +join ( + select distinct ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Security & Reliability.Intel® Remote Platform Erase (RPE) ‡' + and Value = 'Yes' +) IntelProductsWithIntelBootGuard +on Products.ProductType = IntelProductsWithIntelBootGuard.ProductType +and Products.ProductBrand = IntelProductsWithIntelBootGuard.ProductBrand +and Products.ProductSerie = IntelProductsWithIntelBootGuard.ProductSerie +and Products.Id = IntelProductsWithIntelBootGuard.ProductId; + +-- 16. Which is the maximum Temperature Junction allowed by the 9th Gen Intel Core processor that has the greater number of cores? + +select + Products.Name, + Products.Url, + ProductsWithMaxTJunction.Value as "Maximum Temperature Junction" +from Products +join ( + select ProductsSpecifications.* + from ProductsSpecifications + join ( + select distinct + ProductsSpecifications.ProductType, + ProductsSpecifications.ProductBrand, + ProductsSpecifications.ProductSerie, + ProductsSpecifications.ProductId + from ProductsSpecifications + join ( + select ProductType, ProductBrand, ProductSerie, max(Value::numeric) as "Max Total Cores" + from ProductsSpecifications P2 + where (ProductType, ProductBrand, ProductSerie) in ( + select ProductType, ProductBrand, Id as ProductSerie + from ProductSeries + where Name like '9th Generation Intel® Core™' || '%' || 'Processors' + ) + and Specification = 'CPU Specifications.Total Cores' + group by ProductType, ProductBrand, ProductSerie + ) MaxCoresBySeries + on ProductsSpecifications.ProductType = MaxCoresBySeries.ProductType + and ProductsSpecifications.ProductBrand = MaxCoresBySeries.ProductBrand + and ProductsSpecifications.ProductSerie = MaxCoresBySeries.ProductSerie + where Specification = 'CPU Specifications.Total Cores' + and Value::numeric = "Max Total Cores" + ) ProductsWithMaxCores + on ProductsSpecifications.ProductType = ProductsWithMaxCores.ProductType + and ProductsSpecifications.ProductBrand = ProductsWithMaxCores.ProductBrand + and ProductsSpecifications.ProductSerie = ProductsWithMaxCores.ProductSerie + and ProductsSpecifications.ProductId = ProductsWithMaxCores.ProductId + and Specification = 'Package Specifications.TJUNCTION' +) ProductsWithMaxTJunction +on Products.ProductType = ProductsWithMaxTJunction.ProductType +and Products.ProductBrand = ProductsWithMaxTJunction.ProductBrand +and Products.ProductSerie = ProductsWithMaxTJunction.ProductSerie +and Products.Id = ProductsWithMaxTJunction.ProductId; + +-- 17. Which platforms are “Edge” enabled? (prepared for “Edge Applications”) + +select Name, Url +from Products +join ( + select distinct ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where value like '%' || 'Edge Enhanced' || '%' +) IntelEdgeProducts +on Products.ProductType = IntelEdgeProducts.ProductType +and Products.ProductBrand = IntelEdgeProducts.ProductBrand +and Products.ProductSerie = IntelEdgeProducts.ProductSerie +and Products.Id = IntelEdgeProducts.ProductId; + +-- 18. Which are the different Code Names? + +select distinct Value as "Code Names" +from ProductsSpecifications +where Specification = 'Essentials.Code Name' + +-- 19. Which are the different Intel GPUs? + +select Name, Url +from Products +where ProductType = ( + select Id + from ProductTypes + where Name = 'Graphics' +); + +-- 20. Which are the different Elkhart Lake Products? + +select Products.Name, Products.Url +from Products +join ( + select distinct ProductType, ProductBrand, ProductSerie, ProductId + from ProductsSpecifications + where Specification = 'Essentials.Code Name' + and Value = 'Products formerly Elkhart Lake' +) ElkhartLakeProducts +on Products.ProductType = ElkhartLakeProducts.ProductType +and Products.ProductBrand = ElkhartLakeProducts.ProductBrand +and Products.ProductSerie = ElkhartLakeProducts.ProductSerie +and Products.Id = ElkhartLakeProducts.ProductId; diff --git a/rd.png b/rd.png new file mode 100644 index 0000000..03211fa Binary files /dev/null and b/rd.png differ diff --git a/schema.sql b/schema.sql index 70c55c6..29a9a2c 100644 --- a/schema.sql +++ b/schema.sql @@ -43,42 +43,20 @@ CREATE TABLE Products ( CONSTRAINT UQ_Product_Url UNIQUE (Url) ); -CREATE TABLE SpecificationCategories ( - Id INT NOT NULL, - Name TEXT NOT NULL, - - CONSTRAINT PK_SpecificationCategories PRIMARY KEY (Id), - CONSTRAINT UQ_SpecificationCategories_Name UNIQUE (Name) -); - -CREATE TABLE SpecificationProperties ( - SpecificationCategory INT NOT NULL, - Id INT NOT NULL, - Name TEXT NOT NULL, - - CONSTRAINT PK_SpecificationProperties PRIMARY KEY (SpecificationCategory, Id), - CONSTRAINT FK_SpecificationProperties_SpecificationCategories FOREIGN KEY (SpecificationCategory) REFERENCES SpecificationCategories (Id), - CONSTRAINT UQ_SpecificationProperties_Name UNIQUE (Name) -); - CREATE TABLE ProductsSpecifications ( ProductType INT NOT NULL, ProductBrand INT NOT NULL, ProductSerie INT NOT NULL, ProductId INT NOT NULL, - SpecificationCategory INT NOT NULL, - SpecificationProperty INT NOT NULL, + Specification TEXT NOT NULL, Value TEXT NOT NULL, - CONSTRAINT PK_ProductsSpecifications PRIMARY KEY (ProductType, ProductBrand, ProductSerie, ProductId, SpecificationCategory, SpecificationProperty), - CONSTRAINT FK_ProductsSpecifications_Products FOREIGN KEY (ProductType, ProductBrand, ProductSerie, ProductId) REFERENCES Products (ProductType, ProductBrand, ProductSerie, Id), - CONSTRAINT FK_ProductsSpecifications_SpecificationProperties FOREIGN KEY (SpecificationCategory, SpecificationProperty) REFERENCES SpecificationProperties (SpecificationCategory, Id) + CONSTRAINT PK_ProductsSpecifications PRIMARY KEY (ProductType, ProductBrand, ProductSerie, ProductId, Specification), + CONSTRAINT FK_ProductsSpecifications_Products FOREIGN KEY (ProductType, ProductBrand, ProductSerie, ProductId) REFERENCES Products (ProductType, ProductBrand, ProductSerie, Id) ); DROP TABLE ProductTypes; DROP TABLE ProductBrands; DROP TABLE ProductSeries; DROP TABLE Products; -DROP TABLE SpecificationCategories; -DROP TABLE SpecificationProperties; DROP TABLE ProductsSpecifications;