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 |