Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions sql/task1.sql
Original file line number Diff line number Diff line change
@@ -1,14 +1,71 @@
-- Problem 1: Retrieve all products in the Sports category
-- Write an SQL query to retrieve all products in a specific category.

-- Select the name from products to be outputted. Category id is related in Categories and Products so join them
-- Looking for the category id that is equal to 8
SELECT
P.product_name
FROM
Products P
INNER JOIN
Categories C ON P.category_id = C.category_id
WHERE
C.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.

--Need User ID, Username and keep count of the number of orders for each user ID
-- Joining user_id in both orders and users
SELECT
U.user_id,
U.username,
COUNT(O.order_id) AS total_orders
FROM
Users U
LEFT JOIN
Orders O ON U.user_id = O.user_id
GROUP BY
U.user_id, U.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.

--Need to Average the ratings
--Join the product_id from reviews to products
SELECT
P.product_id,
P.product_name,
AVG(R.rating) AS Avg_Ratings
FROM
Products P
JOIN
Reviews R ON P.product_id = R.product_id
GROUP BY
P.product_id, P.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.

--LIMIT 5 at the end for the top 5 users
--Need the SUM of the total amount in Orders
--Join user_id from users and orders to have corresponding users to orders
--Filter the amount spent in a descending order from most spent to least amount spent
SELECT
U.user_id,
U.username,
SUM(O.total_amount) AS total_amount_spent
FROM
Users U
INNER JOIN
Orders O ON U.user_id = O.user_id
GROUP BY
U.user_id, U.username
ORDER BY
total_amount_spent DESC
LIMIT 5;
87 changes: 86 additions & 1 deletion sql/task2.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,102 @@
-- 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.

--Same idea as problem 3 but order the average rating in descending order from highest avg rating to lowest avg rating
SELECT
P.product_id,
P.product_name,
AVG(R.rating) AS average_rating
FROM
Products P
LEFT JOIN
Reviews R ON P.product_id = R.product_id
GROUP BY
P.product_id, P.product_name
ORDER BY
average_rating DESC;


-- 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.

--Join Users, Orders, Order Items, Products and Categories tables together
--Use subquery in WHERE to filter users who have made at least one order in each category by checking
-- counts of distinct categories for each users
--HAVING ensures the count for distinct categories matches the number of distinct categories in the Categories table
SELECT DISTINCT
U.user_id,
U.username,
FROM
Users U
JOIN
Orders O ON U.user_id = O.user_id
JOIN
Order_Items OI ON O.order_id = OI.order_id
JOIN
Products P ON OI.product_id = P.product_id
JOIN
Categories C ON P.category_id = C.category_id
WHERE
U.user_id IN (
SELECT DISTINCT
U2.user_id
FROM
Users U2
JOIN
Orders O2 ON U2.user_id = O2.user_id
JOIN
Order_Items OI2 ON O2.order_id = OI2.order_id
JOIN
Products P2 ON OI2.product_id = P2.product_id
JOIN
Categories C2 ON P2.category_id = C2.category_id
GROUP BY
U2.user_id, C2.category_id
HAVING
COUNT(DISTINCT C2.category_id) = (SELECT COUNT(DISTINCT category_id)FROM Categories)
);

-- 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.

--Join product_id from reviews and products
--only output the product_id and name if the review_id is NULL (empty/not exist) for any product_id in Products
SELECT
P.product_id, P.product_name
FROM
Products P
LEFT JOIN
Reviews R ON P.product_id = R.product_id
WHERE
R.review_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.
-- Hint: You may need to use subqueries or window functions to solve this problem.

--Using CTE to create a new table for OrderedOrders
--Use LEAD() window function to get next order_date for each row from the result set
--Partition result set by user id so the lead function is applied independently to each user and order the rows by order date within each partition
--Assign the above results into a new column called next_order_date
--WHERE filters wanted results that have a difference between consecutive orders of 1 day or next order date is NULL
WITH OrderedOrders AS (
SELECT
user_id,
order_id,
order_date,
LEAD(order_date) OVER (PARTITION BY user_id ORDER BY order_date) AS next_order_date
FROM
Orders
)
SELECT DISTINCT U.user_id, U.username
FROM
Users U
JOIN
OrderedOrders O ON U.user_id = O.user_id
WHERE
DATEDIFF(next_order_date, order_date) = 1 OR next_order_date IS NULL;
79 changes: 79 additions & 0 deletions sql/task3.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,96 @@
-- 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.

--Use CTE called Category_Sales to include category_id, category_name and the sum of total_amount which would be the total_sales
--join all corresponding ids (such as category, product and order) from categories with products, order_items and orders
WITH Category_Sales AS (
SELECT
C.category_id,
C.category_name,
SUM(O.total_amount) AS total_sales
FROM
Categories C
JOIN
Products P ON C.category_id = P.category_id
JOIN
Order_Items OI ON P.product_id = OI.product_id
JOIN
Orders O ON OI.order_id = O.order_id
GROUP BY
C.category_id, C.category_name
)

--Select the category id, name and total sales as output from the new table and order it by having the highest total sales at the top
SELECT
category_id,
category_name,
total_sales
FROM
Category_Sales
ORDER BY
total_sales 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.

--Filter products to those in "Toys & Games"
--HAVING used to make sure the count of distinct product IDs for each user is = total number of products in "Toys & Games" category
SELECT
U.user_id,
U.username
FROM
Users U
JOIN
Orders O ON U.user_id = O.user_id
JOIN
Order_Items OI ON O.order_id = OI.order_id
JOIN
Products P ON OI.product_id = P.product_id
WHERE
P.category_id = 5
GROUP BY
U.user_id, U.username
HAVING
COUNT(DISTINCT P.product_id) = (
SELECT COUNT(*)
FROM Products
WHERE category_id = 5
);

-- 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.

--Make a CTE called Ranked_Products and use ROW_NUMBER() function to assign ranks to each product within its category based on prices in desc order
--ORDER BY in OVER clause ensures that the ranking is reset for each category
--Main query selects products from the CTW where row_num will equal 1 -> meaning it'll select the products has the highest price in each category
WITH Ranked_Products AS (
SELECT
product_id,
product_name,
category_id,
price,
ROW_NUMBER() OVER (PARTITION BY category_id ORDER BY price DESC) AS row_num
FROM
Products
)

SELECT
product_id,
product_name,
category_id,
price
FROM
Ranked_Products
WHERE
row_num = 1;

-- 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.