Products To Multiple Categories SQL Query and Relationship
Ecommerce and pos projects have products tables and also order, categories , items table. Those table are related to each other by foreign key. Here in this blog we will learn how a database design is done for ecommerce website.
Create Products Table
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
status ENUM('active', 'inactive') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP NULL
);Create Categories Table
CREATE TABLE categories (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);Create product_category relationship table
CREATE TABLE product_category (
product_id INT,
category_id INT,
PRIMARY KEY (product_id, category_id),
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE,
FOREIGN KEY (category_id) REFERENCES categories(id) ON DELETE CASCADE
);Create Other Tables
-- Create orders table
CREATE TABLE orders (
id INT AUTO_INCREMENT PRIMARY KEY,
customer_name VARCHAR(255) NOT NULL,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
status ENUM('pending', 'completed', 'cancelled') DEFAULT 'pending',
total DECIMAL(10, 2) NOT NULL
);
-- Create order_items table (One-to-Many relationship with orders and products)
CREATE TABLE order_items (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT,
product_id INT,
quantity INT NOT NULL,
price DECIMAL(10, 2) NOT NULL,
FOREIGN KEY (order_id) REFERENCES orders(id) ON DELETE CASCADE,
FOREIGN KEY (product_id) REFERENCES products(id) ON DELETE CASCADE
);Let's insert some bulk data to these tables
-- Insert data into categories table
INSERT INTO categories (name, description) VALUES
('Electronics', 'Devices and gadgets'),
('Clothing', 'Apparel and fashion items'),
('Home & Kitchen', 'Furniture and kitchen appliances');
-- Insert data into products table
INSERT INTO products (name, price, status, created_at) VALUES
('Laptop', 1200.00, 'active', NOW()),
('Smartphone', 800.00, 'active', NOW()),
('Blender', 150.00, 'inactive', NOW()),
('Shirt', 25.00, 'active', NOW());
-- Insert data into product_category table (linking products to categories)
INSERT INTO product_category (product_id, category_id) VALUES
(1, 1), -- Laptop -> Electronics
(2, 1), -- Smartphone -> Electronics
(3, 3), -- Blender -> Home & Kitchen
(4, 2); -- Shirt -> Clothing
-- Insert data into orders table
INSERT INTO orders (customer_name, total, status, order_date) VALUES
('John Doe', 2000.00, 'completed', NOW()),
('Jane Smith', 75.00, 'pending', NOW());
-- Insert data into order_items table (linking orders to products)
INSERT INTO order_items (order_id, product_id, quantity, price) VALUES
(1, 1, 1, 1200.00),
(1, 2, 1, 800.00),
(2, 4, 3, 25.00);
Now its time to run some queries
- Find all the products related to Electronics category
- Find all the products where price is between 100 to 900 along with category name
- Find total products for each category
Find all the products related to Electronics category
SELECT p.id, p.name, p.price, p.status, p.created_at FROM products p JOIN product_category pc ON p.id = pc.product_id JOIN categories c ON pc.category_id = c.id WHERE c.name = 'Electronics';
Output:
|id |name |price|status|created_at | |---|----------|-----|------|-------------------| |1 |Laptop |1,200|active|2024-11-07 03:13:59| |2 |Smartphone|800 |active|2024-11-07 03:13:59|
Find all the products where price is between 100 to 900 along with category name
SELECT p.id, p.name, p.price, p.status, p.created_at, c.name AS category_name
FROM products p
JOIN product_category pc ON p.id = pc.product_id
JOIN categories c ON pc.category_id = c.id
WHERE p.price BETWEEN 100 AND 900;Output:
|id |name |price|status |created_at |category_name | |---|----------|-----|--------|-------------------|--------------| |2 |Smartphone|800 |active |2024-11-07 03:13:59|Electronics | |3 |Blender |150 |inactive|2024-11-07 03:13:59|Home & Kitchen|
Find total products for each category
SELECT c.name AS category_name, COUNT(p.id) AS total_products
FROM categories c
JOIN product_category pc ON c.id = pc.category_id
JOIN products p ON pc.product_id = p.id
GROUP BY c.id;Output:
|category_name |total_products| |--------------|--------------| |Clothing |1 | |Electronics |2 | |Home & Kitchen|1 |