diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..cee1e924d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,14 @@ +{ + "sqltools.connections": [ + { + "previewLimit": 50, + "server": "localhost", + "port": 5432, + "askForPassword": true, + "driver": "PostgreSQL", + "username": "Hersh", + "name": "ShopifyDB", + "database": "ShopifyDB" + } + ] +} \ No newline at end of file diff --git a/sql/task1.sql b/sql/task1.sql index 90de336ca..7bf920e9a 100644 --- a/sql/task1.sql +++ b/sql/task1.sql @@ -1,14 +1,7 @@ --- Problem 1: Retrieve all products in the Sports category +-- Problem 1: Retrieve all products in the Sports & Outdoors category -- Write an SQL query to retrieve all products in a specific category. --- 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. - --- 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. - --- 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 P.product_id, P.product_name, P.description, P.price +FROM Products AS P +JOIN Categories AS C ON P.category_id = C.category_id +WHERE C.category_name = 'Sports & Outdoors'; \ No newline at end of file diff --git a/sql/task10.sql b/sql/task10.sql new file mode 100644 index 000000000..7848b2146 --- /dev/null +++ b/sql/task10.sql @@ -0,0 +1,26 @@ +-- 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. + +WITH ToysGamesProducts AS ( + SELECT product_id + FROM Products + JOIN Categories ON Products.category_id = Categories.category_id + WHERE Categories.category_name = 'Toys & Games' +), UserOrdersForToysGames AS ( + SELECT Orders.user_id, Order_Items.product_id + FROM Orders + JOIN Order_Items ON Orders.order_id = Order_Items.order_id + WHERE Order_Items.product_id IN (SELECT product_id FROM ToysGamesProducts) + GROUP BY Orders.user_id, Order_Items.product_id +), UserCount AS ( + SELECT user_id, COUNT(*) AS product_count + FROM UserOrdersForToysGames + GROUP BY user_id + HAVING COUNT(*) = (SELECT COUNT(*) FROM ToysGamesProducts) +) + +SELECT Users.user_id, Users.username +FROM Users +JOIN UserCount ON Users.user_id = UserCount.user_id; diff --git a/sql/task11.sql b/sql/task11.sql new file mode 100644 index 000000000..4d808ac11 --- /dev/null +++ b/sql/task11.sql @@ -0,0 +1,25 @@ +-- 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. + +WITH RankedProducts AS ( + SELECT + product_id, + product_name, + category_id, + price, + RANK() OVER (PARTITION BY category_id ORDER BY price DESC) AS price_rank + FROM + Products +) + +SELECT + product_id, + product_name, + category_id, + price +FROM + RankedProducts +WHERE + price_rank = 1; diff --git a/sql/task12.sql b/sql/task12.sql new file mode 100644 index 000000000..09a4d04fb --- /dev/null +++ b/sql/task12.sql @@ -0,0 +1,42 @@ +-- 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. + +WITH OrderedDates AS ( + SELECT + user_id, + order_date, + LAG(order_date) OVER (PARTITION BY user_id ORDER BY order_date) AS prev_order_date, + LEAD(order_date) OVER (PARTITION BY user_id ORDER BY order_date) AS next_order_date + FROM + Orders +), +ConsecutiveOrders AS ( + SELECT + user_id, + order_date, + CASE + WHEN order_date = prev_order_date + INTERVAL '1 day' OR + order_date = next_order_date - INTERVAL '1 day' THEN 1 + ELSE 0 + END AS is_consecutive + FROM + OrderedDates +), +ConsecutiveGroups AS ( + SELECT + user_id, + SUM(is_consecutive) OVER (PARTITION BY user_id ORDER BY order_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS consecutive_days + FROM + ConsecutiveOrders +) +SELECT DISTINCT + U.user_id, + U.username +FROM + Users U +JOIN + ConsecutiveGroups CG ON U.user_id = CG.user_id +WHERE + consecutive_days >= 2; diff --git a/sql/task2.sql b/sql/task2.sql index ad2596731..23874eb64 100644 --- a/sql/task2.sql +++ b/sql/task2.sql @@ -1,19 +1,9 @@ --- Problem 5: Retrieve the products with the highest average rating --- Write an SQL query to retrieve the products with the highest average rating. --- 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. +-- 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. --- 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. - --- 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. - --- 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 +SELECT U.user_id, U.username, COUNT(O.order_id) AS total_orders +FROM Users AS U +LEFT JOIN Orders AS O ON U.user_id = O.user_id +GROUP BY U.user_id, U.username +ORDER BY U.user_id; diff --git a/sql/task3.sql b/sql/task3.sql index f078a9439..25d47e517 100644 --- a/sql/task3.sql +++ b/sql/task3.sql @@ -1,19 +1,9 @@ --- Problem 9: Retrieve the top 3 categories with the highest total sales amount --- Write an SQL query to retrieve the top 3 categories with the highest total sales amount. --- 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. +-- 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. --- 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. - --- 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. - --- 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. +SELECT P.product_id, P.product_name, AVG(R.rating) AS average_rating +FROM Products AS P +LEFT JOIN Reviews AS R ON P.product_id = R.product_id +GROUP BY P.product_id, P.product_name +ORDER BY P.product_id; diff --git a/sql/task4.sql b/sql/task4.sql new file mode 100644 index 000000000..b78b0aa28 --- /dev/null +++ b/sql/task4.sql @@ -0,0 +1,10 @@ +-- 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 U.user_id, U.username, SUM(O.total_amount) AS total_spent +FROM Users AS U +JOIN Orders AS O ON U.user_id = O.user_id +GROUP BY U.user_id, U.username +ORDER BY total_spent DESC +LIMIT 5; \ No newline at end of file diff --git a/sql/task5.sql b/sql/task5.sql new file mode 100644 index 000000000..14f22017c --- /dev/null +++ b/sql/task5.sql @@ -0,0 +1,21 @@ +-- Problem 5: Retrieve the products with the highest average rating +-- Write an SQL query to retrieve the products with the highest average rating. +-- 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. + +WITH ProductRatings AS ( + SELECT + P.product_id, + P.product_name, + AVG(R.rating) AS average_rating + FROM Products AS P + LEFT JOIN Reviews AS R ON P.product_id = R.product_id + GROUP BY P.product_id, P.product_name +) + +SELECT product_id, product_name, average_rating +FROM ProductRatings +WHERE average_rating = ( + SELECT MAX(average_rating) + FROM ProductRatings +); \ No newline at end of file diff --git a/sql/task6.sql b/sql/task6.sql new file mode 100644 index 000000000..5e0f36671 --- /dev/null +++ b/sql/task6.sql @@ -0,0 +1,20 @@ +-- 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 + 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 +GROUP BY + U.user_id, U.username +HAVING + COUNT(DISTINCT P.category_id) = (SELECT COUNT(*) FROM Categories); diff --git a/sql/task7.sql b/sql/task7.sql new file mode 100644 index 000000000..4fe678950 --- /dev/null +++ b/sql/task7.sql @@ -0,0 +1,9 @@ +-- 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 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; \ No newline at end of file diff --git a/sql/task8.sql b/sql/task8.sql new file mode 100644 index 000000000..2bf9fae15 --- /dev/null +++ b/sql/task8.sql @@ -0,0 +1,23 @@ +-- 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. + +WITH OrderedUsers AS ( + SELECT + U.user_id, + U.username, + O.order_date, + LAG(O.order_date) OVER (PARTITION BY U.user_id ORDER BY O.order_date) AS prev_order_date + FROM + Orders O + JOIN Users U ON O.user_id = U.user_id +) + +SELECT DISTINCT + user_id, + username +FROM + OrderedUsers +WHERE + order_date = DATE_ADD(prev_order_date, INTERVAL 1 DAY); diff --git a/sql/task9.sql b/sql/task9.sql new file mode 100644 index 000000000..f09ec5ddc --- /dev/null +++ b/sql/task9.sql @@ -0,0 +1,20 @@ +-- Problem 9: Retrieve the top 3 categories with the highest total sales amount +-- Write an SQL query to retrieve the top 3 categories with the highest total sales amount. +-- 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 + C.category_id, + C.category_name, + SUM(OI.quantity * OI.unit_price) AS total_sales_amount +FROM + Categories C +JOIN + Products P ON C.category_id = P.category_id +JOIN + Order_Items OI ON P.product_id = OI.product_id +GROUP BY + C.category_id, C.category_name +ORDER BY + total_sales_amount DESC +LIMIT 3; diff --git a/tests/test_sql_queries.py b/tests/test_sql_queries.py index 22b25d546..2fe06d3f7 100644 --- a/tests/test_sql_queries.py +++ b/tests/test_sql_queries.py @@ -6,11 +6,11 @@ class TestSQLQueries(unittest.TestCase): def setUp(self): # Establish a connection to your test database self.conn = psycopg2.connect( - dbname='your_dbname', - user='your_username', - password='your_password', - host='your_host', - port='your_port' + dbname='ShopifyDB', + user='Hersh', + password='123', + host='localhost', + port='5432' ) self.cur = self.conn.cursor() @@ -29,7 +29,8 @@ def test_task1(self): # Define expected outcome for Task 1 and compare expected_result = [ - # Define expected rows or values here based on the query output + [15, 'Mountain Bike', 'Conquer the trails with this high-performance mountain bike.', 1000.0], + [16, 'Tennis Racket', 'Take your tennis game to the next level with this professional-grade racket.', 54.0] ] self.assertEqual(result, expected_result, "Task 1: Query output doesn't match expected result.") @@ -44,12 +45,219 @@ def test_task2(self): # Define expected outcome for Task 2 and compare expected_result = [ - # Define expected rows or values here based on the query output + [1, 'johndoe', 1], + [2, 'janesmith', 1], + [3, 'maryjones', 1], + [4, 'robertbrown', 1], + [5, 'sarahwilson', 1], + [6, 'michaellee', 1], + [7, 'lisawilliams', 1], + [8, 'chrisharris', 1], + [9, 'emilythompson', 1], + [10, 'davidmartinez', 1], + [11, 'amandajohnson', 1], + [12, 'jasonrodriguez', 1], + [13, 'ashleytaylor', 1], + [14, 'matthewthomas', 1], + [15, 'sophiawalker', 1], + [16, 'jacobanderson', 1], + [17, 'olivialopez', 1], + [18, 'ethanmiller', 1], + [19, 'emilygonzalez', 1], + [20, 'williamhernandez', 1], + [21, 'sophiawright', 1], + [22, 'alexanderhill', 1], + [23, 'madisonmoore', 1], + [24, 'jamesrogers', 1], + [25, 'emilyward', 1], + [26, 'benjamincarter', 1], + [27, 'gracestewart', 1], + [28, 'danielturner', 1], + [29, 'elliecollins', 1], + [30, 'williamwood', 1] ] self.assertEqual(result, expected_result, "Task 2: Query output doesn't match expected result.") - # Add more test methods for additional SQL tasks + def test_task3(self): + # Task 3: Example SQL query in task3.sql + with open('/sql/task3.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 3 and compare + expected_result = [ + [1, 'Smartphone X', 5.0], + [2, 'Wireless Headphones', 4.0], + [3, 'Laptop Pro', 3.0], + [4, 'Smart TV', 5.0], + [5, 'Running Shoes', 2.0], + [6, 'Designer Dress', 4.0], + [7, 'Coffee Maker', 5.0], + [8, 'Toaster Oven', 3.0], + [9, 'Action Camera', 4.0], + [10, 'Board Game Collection', 1.0], + [11, 'Yoga Mat', 5.0], + [12, 'Skincare Set', 4.0], + [13, 'Vitamin C Supplement', 2.0], + [14, 'Weighted Blanket', 3.0], + [15, 'Mountain Bike', 5.0], + [16, 'Tennis Racket', 4.0] + ] + + self.assertEqual(result, expected_result, "Task 3: Query output doesn't match expected result.") + + def test_task4(self): + # Task 4: Example SQL query in task4.sql + with open('/sql/task4.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 4 and compare + expected_result = [ + [12, 'jasonrodriguez', 160.0], + [4, 'robertbrown', 155.0], + [8, 'chrisharris', 150.0], + [24, 'jamesrogers', 150.0], + [17, 'olivialopez', 145.0] + ] + + self.assertEqual(result, expected_result, "Task 4: Query output doesn't match expected result.") + + def test_task5(self): + # Task 5: Example SQL query in task5.sql + with open('/sql/task5.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 5 and compare + expected_result = [ + [1, 'Smartphone X', 5.0], + [4, 'Smart TV', 5.0], + [7, 'Coffee Maker', 5.0], + [11, 'Yoga Mat', 5.0], + [15, 'Mountain Bike', 5.0] + # Products with IDs 18, 21, 25, and 29 also have the highest average rating of 5.0, + # but their names are missing in the provided dataset. + ] + + self.assertEqual(result, expected_result, "Task 5: Query output doesn't match expected result.") + + def test_task6(self): + # Task 6: Example SQL query in task6.sql + with open('/sql/task6.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 6 and compare + expected_result = [ + ] + + self.assertEqual(result, expected_result, "Task 6: Query output doesn't match expected result.") + + def test_task7(self): + # Task 7: Example SQL query in task7.sql + with open('/sql/task7.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 7 and compare + expected_result = [ + ] + + self.assertEqual(result, expected_result, "Task 7: Query output doesn't match expected result.") + + def test_task8(self): + # Task 8: Example SQL query in task8.sql + with open('/sql/task8.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 8 and compare + expected_result = [ + ] + + self.assertEqual(result, expected_result, "Task 8: Query output doesn't match expected result.") + + def test_task9(self): + # Task 9: Example SQL query in task9.sql + with open('/sql/task9.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 9 and compare + expected_result = [ + [1, 'Electronics', 155.00], + [3, 'Clothing', 145.00], + [5, 'Toys & Games', 125.00] + ] + + self.assertEqual(result, expected_result, "Task 9: Query output doesn't match expected result.") + + def test_task10(self): + # Task 10: Example SQL query in task10.sql + with open('/sql/task10.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 10 and compare + expected_result = [ + [5, 'sarahwilson'], + ] + + self.assertEqual(result, expected_result, "Task 10: Query output doesn't match expected result.") + + def test_task11(self): + # Task 11: Example SQL query in task11.sql + with open('/sql/task11.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 11 and compare + expected_result = [ + [1, 'Smartphone X', 1, 500.00], + [3, 'Laptop Pro', 2, 1200.00], + [6, 'Designer Dress', 3, 300.00] + [7, 'Coffee Maker', 4, 80.00], + [9, 'Action Camera', 5, 200.00], + [12, 'Skincare Set', 6, 150.00] + [14, 'Weighted Blanket', 7, 100.00], + [15, 'Mountain Bike', 8, 1000.00], + ] + + self.assertEqual(result, expected_result, "Task 11: Query output doesn't match expected result.") + + def test_task12(self): + # Task 12: Example SQL query in task12.sql + with open('/sql/task12.sql', 'r') as file: + sql_query = file.read() + + self.cur.execute(sql_query) + result = self.cur.fetchall() + + # Define expected outcome for Task 12 and compare + expected_result = [ + ] + + self.assertEqual(result, expected_result, "Task 12: Query output doesn't match expected result.") if __name__ == '__main__': unittest.main() \ No newline at end of file