diff --git a/sql/task1.sql b/sql/task1.sql index 90de336ca..35406a57a 100644 --- a/sql/task1.sql +++ b/sql/task1.sql @@ -1,14 +1,45 @@ -- Problem 1: Retrieve all products in the Sports category -- Write an SQL query to retrieve all products in a specific category. +-- Select all from products table where category id is 8 (sports). +SELECT * FROM product_data WHERE category_id = '8'; + -- Problem 2: Retrieve the total number of orders for each user -- Write an SQL query to retrieve the total number of orders for each user. -- The result should include the user ID, username, and the total number of orders. +-- Select columns user_id and username and count order_id from order_data +SELECT user.user_id, user.username, +COUNT(ord.order_id) AS total_amount FROM user_data user +-- JOIN user_data with order_data +JOIN order_data ord ON user.user_id = ord.user_id +-- Group results by user ID and username. +GROUP BY user.user_id, user.username; + -- Problem 3: Retrieve the average rating for each product -- Write an SQL query to retrieve the average rating for each product. -- The result should include the product ID, product name, and the average rating. +-- Select columns of product_id and product_name, and the average rating +SELECT pr.product_id, pr.product_name, +-- Calculate average rating +AVG(re.rating) AS average_rating FROM product_data pr +-- Join review_data from product_data and match product_id in both tables +JOIN review_data re ON pr.product_id = re.product_id +-- group by product id and product name. +GROUP BY pr.product_id, pr.product_name; + -- Problem 4: Retrieve the top 5 users with the highest total amount spent on orders -- Write an SQL query to retrieve the top 5 users with the highest total amount spent on orders. -- The result should include the user ID, username, and the total amount spent. + +-- Select columns of user_id and username, and sum of total_amount. +SELECT us.user_id, us.username, +-- Calculate sum +SUM(ord.total_amount) AS total_amount_spent FROM user_data us +-- join order_data with user_data and match user_id with both tables. +JOIN order_data ord ON us.user_id = ord.user_id +-- group results by user id and username. +GROUP BY us.user_id, us.username +-- order results by descending order and limit to top 5. +ORDER BY total_amount_spent DESC LIMIT 5; diff --git a/sql/task2.sql b/sql/task2.sql index ad2596731..8ed28f328 100644 --- a/sql/task2.sql +++ b/sql/task2.sql @@ -3,17 +3,68 @@ -- The result should include the product ID, product name, and the average rating. -- Hint: You may need to use subqueries or common table expressions (CTEs) to solve this problem. +-- Select product id, name, and average rating. +SELECT pr.product_id, pr.product_name, +-- Calculate average rating +AVG(re.rating) AS average_rating +-- Join review_data with product_data and match product_id in both tables. +FROM product_data pr JOIN review_data re ON pr.product_id = re.product_id +-- Group results by product id and name. +GROUP BY pr.product_id, pr.product_name +-- Filter results to show only products with the highest average rating +HAVING AVG(re.rating) = ( +-- Create a subquery to find the highest average rating among each product. + SELECT MAX(average_rating) FROM ( + -- Calculate average rating for each product. + SELECT AVG(rating) AS average_rating FROM review_data GROUP BY product_id + ) + AS SubQuery + ); + -- Problem 6: Retrieve the users who have made at least one order in each category -- Write an SQL query to retrieve the users who have made at least one order in each category. -- The result should include the user ID and username. -- Hint: You may need to use subqueries or joins to solve this problem. +-- Select user ID and username. +SELECT us.user_id, us.username FROM user_data us +-- Join order_data with user_data. +JOIN order_data ord ON us.user_id = ord.user_id +-- Join order_items_data with order_data. +JOIN order_items_data oid ON ord.order_id = oid.order_id +-- Join prudct_data with order_items_data. +JOIN product_data pr ON oid.product_id = pr.product_id +-- Group results by user_id and username. +GROUP BY us.user_id, us.username +-- Filter results to only show user who have ordered at least once in each category. +HAVING COUNT(DISTINCT pr.category_id) = ( +-- Create a subquery to count the total number of distinct categories + SELECT COUNT(*) FROM category_data +); + -- Problem 7: Retrieve the products that have not received any reviews -- Write an SQL query to retrieve the products that have not received any reviews. -- The result should include the product ID and product name. -- Hint: You may need to use subqueries or left joins to solve this problem. +-- Select product_id and product_name +SELECT pr.product_id, pr.product_name FROM product_data pr +-- Do a left join with review_data on product_id +LEFT JOIN review_data re ON pr.product_id = re.product_id +-- Filter results to show only products without any reviews. +WHERE re.product_id IS NULL; + -- Problem 8: Retrieve the users who have made consecutive orders on consecutive days -- Write an SQL query to retrieve the users who have made consecutive orders on consecutive days. -- The result should include the user ID and username. --- Hint: You may need to use subqueries or window functions to solve this problem. \ No newline at end of file +-- Hint: You may need to use subqueries or window functions to solve this problem. + +-- Select distinct user_ids and usernames. +SELECT DISTINCT us.user_id, us.username FROM user_data us +-- Join order_data with user_data +JOIN order_data or1 ON us.user_id = or1.user_id +-- Join order_data with user_data again. +JOIN order_data or2 ON us.user_id = or2.user_id +-- Filter results to only show order dates that are consecutive. +WHERE DATE(or1.order_date) = date_add(date(or2.order_date), interval 1 day) +OR DATE(or2.order_date) = date_add(date(or1.order_date), interval 1 day); diff --git a/sql/task3.sql b/sql/task3.sql index f078a9439..acd631427 100644 --- a/sql/task3.sql +++ b/sql/task3.sql @@ -3,17 +3,78 @@ -- The result should include the category ID, category name, and the total sales amount. -- Hint: You may need to use subqueries, joins, and aggregate functions to solve this problem. +-- Select category ID, category name, and total sales amount for every category +SELECT ca.category_id, ca.category_name, +-- Calculate the sum or the total sales amount +sum(od.quantity * od.unit_price) AS total_sales_amount +-- Join products with categories and order_items_data +from categories ca JOIN products pr ON ca.category_id = pr.category_id +JOIN order_items_data od ON pr.product_id = od.product_id +-- Group results by category id and name +GROUP BY ca.category_id, ca.category_name +-- Order results by total sales amount in descending order and limited to the top 3 categories. +ORDER BY total_sales_amount DESC LIMIT 3; + -- Problem 10: Retrieve the users who have placed orders for all products in the Toys & Games -- Write an SQL query to retrieve the users who have placed orders for all products in the Toys & Games -- The result should include the user ID and username. -- Hint: You may need to use subqueries, joins, and aggregate functions to solve this problem. +-- Select user ID and username +SELECT us.user_id, us.username FROM user_data us +-- Join user_data with order +JOIN orders ord ON us.user_id = ord.user_id +-- Join order_items_data with orders +JOIN order_items_data oid ON ord.order_id = oid.order_id +-- Join order_items_data with products +JOIN products pr ON oid.product_id = pr.product_id +-- Join products with categories. +JOIN categories ca ON pr.category_id = ca.category_id +-- Filter by Toys & Games category +WHERE ca.category_name = 'Toys & Games' +-- Group results by user id and username +GROUP BY us.user_id, us.username +-- Filter results to show only users who have placed orders for distinct products in Toys & Games. +HAVING COUNT(distinct pr.product_id) = ( +-- Create a subquery to count total number of distinct products in Toys & Games +select COUNT(distinct product_id) FROM products WHERE category_id = ( +-- Create a subquery to find category_id for Toys & Games category +SELECT category_id FROM categories WHERE category_name = 'Toys & Games' +) +); + -- Problem 11: Retrieve the products that have the highest price within each category -- Write an SQL query to retrieve the products that have the highest price within each category. -- The result should include the product ID, product name, category ID, and price. -- Hint: You may need to use subqueries, joins, and window functions to solve this problem. +-- Select product id, name, category id, and price. +SELECT pr.product_id, pr.product_name, pr.category_id, pr.price FROM products pr +-- Join products with a subquery which finds the max price for every category. +INNER JOIN ( SELECT category_id, MAX(price) AS max_price FROM products +GROUP BY category_id ) +-- Match category id +AS max_prices ON pr.category_id = max_prices.category_id +-- Match product's price with max price. +AND pr.price = max_prices.max_price; + -- Problem 12: Retrieve the users who have placed orders on consecutive days for at least 3 days -- Write an SQL query to retrieve the users who have placed orders on consecutive days for at least 3 days. -- The result should include the user ID and username. -- Hint: You may need to use subqueries, joins, and window functions to solve this problem. + +-- Create a CTE that creates a dataset with user id, username, order date, previous order date and next order date. +WITH DatesOrder AS ( SELECT ord.user_id, us.username, ord.order_date, +-- Use lag to get previous order date for every user. +LAG(ord.order_date, 1) OVER (partition by ord.user_id ORDER BY ord.order_date) AS +previous_order_date, +-- Lead provides the next order date for every user. +LEAD(ord.order_date, 1) OVER (partition by ord.user_id ORDER BY ord.order_date) AS +next_order_date +-- Join orders with user_data +FROM orders ord JOIN user_data us ON ord.user_id = us.user_id ) +-- Select distinct user ids and usernames +SELECT DISTINCT user_id, username +-- Filter results to show users who have ordered on 3 consecutive days +FROM DatesOrder WHERE order_date = date_add(previous_order_date, interval 1 DAY) AND +next_order_date = date_add(order_date, interval 1 day);