{"id":31177862,"url":"https://github.com/jawsee97/8-week-sql-challenge","last_synced_at":"2025-09-19T14:32:16.267Z","repository":{"id":311734290,"uuid":"1044769460","full_name":"Jawsee97/8-week-SQL-Challenge","owner":"Jawsee97","description":"SQL Case Study Project with Solutions","archived":false,"fork":false,"pushed_at":"2025-09-10T05:49:16.000Z","size":59,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-10T09:03:34.787Z","etag":null,"topics":["case-study","data-analysis","data-analytics","mysql-database","postgresql","sql"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jawsee97.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-26T07:22:19.000Z","updated_at":"2025-09-10T05:49:19.000Z","dependencies_parsed_at":"2025-09-03T05:19:29.515Z","dependency_job_id":null,"html_url":"https://github.com/Jawsee97/8-week-SQL-Challenge","commit_stats":null,"previous_names":["jawsee97/8-week-sql-challenge"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/Jawsee97/8-week-SQL-Challenge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jawsee97%2F8-week-SQL-Challenge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jawsee97%2F8-week-SQL-Challenge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jawsee97%2F8-week-SQL-Challenge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jawsee97%2F8-week-SQL-Challenge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jawsee97","download_url":"https://codeload.github.com/Jawsee97/8-week-SQL-Challenge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jawsee97%2F8-week-SQL-Challenge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275952440,"owners_count":25558705,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-19T02:00:09.700Z","response_time":108,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["case-study","data-analysis","data-analytics","mysql-database","postgresql","sql"],"created_at":"2025-09-19T14:31:16.548Z","updated_at":"2025-09-19T14:32:16.258Z","avatar_url":"https://github.com/Jawsee97.png","language":null,"readme":"# 👨🏽‍💻 8-Week SQL Challenges \n\nThis repository serves as the solution for the 1/8 case studies from the **[#8WeekSQLChallenge](https://8weeksqlchallenge.com)**. \n\nIt highlights my capabilities to analyze diverse SQL challenges while demonstrating strong proficiency in query development and problem-solving.\n\n###\n\n# 🍜 Case Study #1: Danny's Diner \n\u003cimg src=\"https://user-images.githubusercontent.com/81607668/127727503-9d9e7a25-93cb-4f95-8bd0-20b87cb4b459.png\" alt=\"Image\" width=\"500\" height=\"500\"\u003e\n\n## 📚 Table of Contents\n- [Business Task](#business-task)\n- [Entity Relationship Diagram](#entity-relationship-diagram)\n- [Question and Solution](#question-and-solution)\n\nPlease note that all the information regarding the case study has been sourced from the following link: [here](https://8weeksqlchallenge.com/case-study-1/). \n\n***\n\n## 📋 Business Task\nDanny wants to analyze customer data to understand visiting patterns, spending habits, and favorite items. These insights will guide loyalty program decisions and provide simple datasets his team can review without using SQL.\n\n***\n\n## 🧬 Entity Relationship Diagram\n\n\u003cimg width=\"717\" height=\"348\" alt=\"Screenshot 2025-08-26 at 12 50 34 AM\" src=\"https://github.com/user-attachments/assets/e3e33bd0-4d59-4251-a2a3-cb2b8722714a\" /\u003e\n\n***\n\n## 🙋🏽‍♂️ Question and Solution\n\nThe Database, along with the queries that will be executed for this project can be found here -\u003e [DB Fiddle](https://www.db-fiddle.com/f/2rM8RAnq7h5LLDTzZiRWcd/138).\n\n\n**1. What is the total amount each customer spent at the restaurant?**\n\n````sql\nSELECT\n\tsales.customer_id,\n    SUM(menu.price) AS total_sales\nFROM dannys_diner.sales\nINNER JOIN dannys_diner.menu\nON sales.product_id = menu.product_id\nGROUP BY sales.customer_id\nORDER BY sales.customer_id ASC;\n````\n#### Steps:\n- Used **JOIN** to merge `dannys_diner.sales` and `dannys_diner.menu` tables as `sales.customer_id` and `menu.price` are from both tables.\n- Used **SUM** to calculate the total sales contributed by each customer.\n- Grouped the aggregated results by `sales.customer_id`. \n\n#### Answer:\n| customer_id | total_sales |\n| ----------- | ----------- |\n| A           | 76          |\n| B           | 74          |\n| C           | 36          |\n\nFrom this Table, we can gather that:\n- Customer A spent $76.\n- Customer B spent $74.\n- Customer C spent $36.\n\n***\n\n**2. How many days has each customer visited the restaurant?**\n\n````sql\nSELECT \n\tcustomer_id,\n    COUNT(DISTINCT order_date) AS visit_count\nFROM dannys_diner.sales\nGROUP BY customer_id;\n````\n\n#### Steps:\n- To determine the unique number of visits for each customer, utilized **COUNT(DISTINCT `order_date`)**.\n- Used the **DISTINCT** keyword to calculate the visit count to avoid duplicate counting of days. For example, if Customer A visited the restaurant twice on '2021–01–07', counting without **DISTINCT** would result in 2 days instead of the accurate count of 1 day.\n\n#### Answer:\n| customer_id | visit_count |\n| ----------- | ----------- |\n| A           | 4          |\n| B           | 6          |\n| C           | 2          |\n\nFrom this Table, we can gather that:\n- Customer A visited 4 times.\n- Customer B visited 6 times.\n- Customer C visited 2 times.\n\n***\n\n**3. What was the first item from the menu purchased by each customer?**\n\n````sql\nWITH ranked_sales AS (\n\tSELECT \n  \t\tsales.customer_id,\n  \t\tsales.order_date,\n  \t\tmenu.product_name,\n  \t\tROW_NUMBER() OVER (\n          PARTITION BY sales.customer_id\n          ORDER BY sales.order_date ASC, sales.product_id ASC\n        ) AS rn\n  \tFROM sales\n  \tJOIN menu\n  \t\tON sales.product_id = menu.product_id\n  )\n  SELECT \n  \tcustomer_id,\n    order_date,\n    product_name AS first_item\n    FROM ranked_sales\n    WHERE rn = 1;\n````\n#### Steps:\n- Used **ROW_NUMBER()** to assign a rank to each purchase per customer ordered by the earliest `order_date`\n- On the off chance that items were bought on the same earliest date, the **ORDER BY sales.product_id** would ensure consistent picking.\n- We lastly filter this query with 'WHERE rn = 1' to keep the first item per customer.\n  \n| customer_id | product_name | \n| ----------- | ----------- |\n| A           | sushi        | \n| B           | curry        | \n| C           | ramen        |\n\nFrom this Table, we can gather that:\n- Customer A placed an order for both curry and sushi simultaneously, making them the first items in the order.\n- Customer B's first order is curry.\n- Customer C's first order is ramen.\n\n  ***\n\n**4. What is the most purchased item on the menu and how many times was it purchased by all customers?**\n\n````sql\nSELECT\n\tmenu.product_name,\n    COUNT(sales.product_id) AS total_purchases\nFROM dannys_diner.sales\nJOIN dannys_diner.menu\nON sales.product_id = menu.product_id\nGROUP BY menu.product_name\nORDER BY total_purchases DESC\nLIMIT 1;\n````\n\n#### Steps:\n- Used a **COUNT** aggregation on the `product_id` column and **ORDER BY** the result in descending order using `total_purchases` field.\n- Used the **LIMIT** 1 clause to filter and retrieve the top-selling item.\n\n#### Answer:\n| most_purchased | product_name | \n| ----------- | ----------- |\n| 8       | ramen |\n\n\nFrom this Table, we can gather that:\n- Ramen is the most purchased item on the menu !\n\n***\n\n**5. Which item was the most popular for each customer?**\n\n````sql\nWITH customer_item_counts AS (\n  SELECT \n  \ts.customer_id,\n  \tm.product_name,\n  \tCOUNT(*) AS purchase_count\n  FROM sales s\n  JOIN menu m\n  \tON s.product_id = m.product_id\n  GROUP BY s.customer_id, m.product_name\n),\nranked_items AS ( \n  SELECT \n  \tcustomer_id,\n  \tproduct_name,\n  \tpurchase_count,\n  \tRANK() OVER (\n      PARTITION BY customer_id\n      ORDER BY purchase_count DESC\n    ) AS rnk\n   FROM customer_item_counts\n  )\n SELECT \n \tcustomer_id,\n    product_name AS most_popular_itme,\n    purchase_count\n FROM ranked_items\n WHERE rnk = 1\n ORDER BY customer_id;\n````\n\n*Each user may have more than 1 favourite item.*\n\n#### Steps:\n- Used a **COUNT** aggregation to see how many times each customer ordered each product `customer_item_counts`.\n- Using `purchase_count` we ranked items per customer\n- Then used the **RANK** function in the case of a tie, we return all top items.\n- Finally, used a filter with `WHERE rnk = 1`.\n\n#### Answer:\n| customer_id | product_name | order_count |\n| ----------- | ---------- |------------  |\n| A           | ramen        |  3   |\n| B           | sushi        |  2   |\n| B           | curry        |  2   |\n| B           | ramen        |  2   |\n| C           | ramen        |  3   |\n\nFrom this Table, we can gather that:\n- Customer A and C's favourite item is ramen.\n- Customer B enjoys all items on the menu.\n\n***\n\n**6. Which item was purchased first by the customer after they became a member?**\n\n```sql\nWITH member_sales AS (\n  SELECT\n  \ts.customer_id,\n  \ts.order_date,\n  \tm.product_name,\n  \tROW_NUMBER() OVER (\n      PARTITION BY s.customer_id\n      ORDER BY s.order_date ASC, s.product_id ASC\n      ) AS rn\n  \tFROM sales s\n  \tJOIN menu m\n  \tON s.product_id = m.product_id\n  \tJOIN members mem\n  \tON s.customer_id = mem.customer_id\n  \tWHERE s.order_date \u003e= mem.join_date\n  )\nSELECT customer_id, order_date, product_name AS first_item_after_join\nFROM member_sales\nWHERE rn = 1\nORDER BY customer_id;\n```\n\n#### Steps:\n- Created a CTE named `member_sales` then selected the appropriate columns and calculated the row number using the **ROW_NUMBER()** function. The **PARTITION BY** clause divides the data by `s.customer_id` and the **ORDER BY** clause orders the rows within each `s.order_date` and `s.product_id` ASC.\n- Then joined the tables `members` and `sales` on `customer_id` column. Additionally, applied a condition to include sales that occurred *On or After* the member's `join_date` (`s.order_date \u003e= mem.join_date`).\n- Then used the **WHERE** clause in the **Outer Query** to filter and retrieve only the rows where the rn column = 1, representing the first row within each `customer_id` partition.\n- Lastly, ordered result by `customer_id`.\n\n#### Answer:\n| customer_id | product_name |\n| ----------- | ---------- |\n| A           | curry        |\n| B           | sushi        |\n\nFrom this Table, we can gather that:\n- Customer A's first order as a member is curry.\n- Customer B's first order as a member is sushi.\n\n***\n\n**7. Which item was purchased just before the customer became a member?**\n\n````sql\nWITH pre_member_sales AS ( \n  SELECT\n  \ts.customer_id,\n  \ts.order_date,\n  \tm.product_name,\n  \tROW_NUMBER() OVER (\n      PARTITION BY s.customer_id\n      ORDER BY s.order_date DESC, s.product_id DESC\n      ) AS rn\n  FROM sales s\n  JOIN menu m \n  \tON s.product_id = m.product_id\n  JOIN members mem\n  \tON s.customer_id = mem.customer_id\n  WHERE s.order_date \u003c mem.join_date\n  )\n  SELECT\n  \tcustomer_id,\n    order_date,\n    product_name AS last_item_before_join\n  FROM pre_member_sales\n  WHERE rn = 1\n  ORDER BY customer_id;\n````\n\n#### Steps:\n- Created a CTE called `pre_member_sales`. \n- Select the appropriate columns and calculate the rank using the **ROW_NUMBER()** window function. The rank is determined based on the order dates of the sales along with the product ID in descending order.\n- Join `dannys_diner.sales` table with `dannys_diner.menu` table and the `dannys_diner.members` table so we can filter by membership join date.\n- Then used the **WHERE** clause to keep sales that only happened before the customer became a member.\n- Then filtered the result set to include only the rows where the rank = 1, representing the earliest purchase made by each customer before they became a member.\n- Finally, sorted the result by `customer_id`.\n\n#### Answer:\n| customer_id | product_name |\n| ----------- | ---------- |\n| A           | curry        |\n| B           | sushi        |\n\nFrom this Table, we can gather that:\n- Customers A last item purchased pre-membership was curry\n- Customers B last item purchased pre-membership was sushi\n\n***\n\n**8. What is the total items and amount spent for each member before they became a member?**\n\n```sql\nSELECT \n\tmem.customer_id,\n    COUNT(s.product_id) AS total_items,\n    SUM(m.price) AS total_amount\nFROM sales s\nJOIN menu m\n\tON s.product_id = m.product_id\nJOIN members mem\n\tON s.customer_id = mem.customer_id\nWHERE s.order_date \u003c mem.join_date\nGROUP BY mem.customer_id\nORDER BY mem.customer_id;\n```\n\n#### Steps:\n- Selected the columns `mem.customer_id` and then used the **COUNT** aggregation to count `sales.product_id` as total_items for each customer. Then used the  **SUM** aggregation to sum the `m.price` as total_sales.\n- Joined the `sales`,`menu`, and `members` table, then used the **WHERE** clause to filter the `s.order_date` and `mem.join_date` to keep only the rows where the purchase date is before the customer's join date.\n- Grouped the results by `mem.customer_id`.\n- Ordered the result by `mem.customer_id`.\n\n#### Answer:\n| customer_id | total_items | total_sales |\n| ----------- | ---------- |----------  |\n| A           | 2 |  25       |\n| B           | 3 |  40       |\n\nFrom this Table, we can gather that:\nBefore becoming members,\n- Customer A spent $25 on 2 items.\n- Customer B spent $40 on 3 items.\n\n***\n\n**9. If each $1 spent equates to 10 points and sushi has a 2x points multiplier — how many points would each customer have?**\n\n```sql\nSELECT s.customer_id,\n\tSUM(\n      CASE\n      \tWHEN m.product_name = 'sushi' THEN m.price * 10 * 2\n      \tELSE m.price * 10\n      END\n     ) AS total_points\nFROM sales s\nJOIN menu m \n\tON s.product_id = m.product_id\nGROUP BY s.customer_id\nORDER BY s.customer_id;\n```\n\n#### Steps:\n- Used a `CASE` expression to calculate points, if product name = sushi, then apply the 2x points multiplier, otherwise, multiply price by 10.\n- Then joined the `sales` and `menu` table\n- Finally Grouped and Ordered rows by `s.customer_id`\n\n#### Answer:\n| customer_id | total_points | \n| ----------- | ---------- |\n| A           | 860 |\n| B           | 940 |\n| C           | 360 |\n\nFrom this Table, we can gather that:\n- Total points for Customer A is $860.\n- Total points for Customer B is $940.\n- Total points for Customer C is $360.\n\n***\n\n**10. In the first week after a customer joins the program (including their join date) they earn 2x points on all items, not just sushi — how many points do customer A and B have at the end of January?**\n\n```sql\nWITH dates_cte AS (\n  SELECT \n    customer_id, \n      join_date, \n      join_date + 6 AS valid_date, \n      DATE_TRUNC(\n        'month', '2021-01-31'::DATE)\n        + interval '1 month' \n        - interval '1 day' AS last_date\n  FROM dannys_diner.members\n)\n\nSELECT \n  sales.customer_id, \n  SUM(CASE\n    WHEN menu.product_name = 'sushi' THEN 2 * 10 * menu.price\n    WHEN sales.order_date BETWEEN dates.join_date AND dates.valid_date THEN 2 * 10 * menu.price\n    ELSE 10 * menu.price END) AS points\nFROM dannys_diner.sales\nINNER JOIN dates_cte AS dates\n  ON sales.customer_id = dates.customer_id\n  AND dates.join_date \u003c= sales.order_date\n  AND sales.order_date \u003c= dates.last_date\nINNER JOIN dannys_diner.menu\n  ON sales.product_id = menu.product_id\nGROUP BY sales.customer_id;\n```\n\n#### Assumptions:\n- On Day -X to Day 1 (the day a customer becomes a member), each $1 spent earns 10 points. However, for sushi, each $1 spent earns 20 points.\n- From Day 1 to Day 7 (the first week of membership), each $1 spent for any items earns 20 points.\n- From Day 8 to the last day of January 2021, each $1 spent earns 10 points. However, sushi continues to earn double the points at 20 points per $1 spent.\n\n#### Steps:\n- Created a CTE called `dates_cte`. \n- In `dates_cte`, calculated the `valid_date` by adding 6 days to the `join_date` and determined the `last_date` of the month by subtracting 1 day from the last day of January 2021.\n- From `dannys_diner.sales` table, joined `dates_cte` on `customer_id` column, ensuring that the `order_date` of the sale is after the `join_date` (`dates.join_date \u003c= sales.order_date`) and not later than the `last_date` (`sales.order_date \u003c= dates.last_date`).\n- Then, joined `dannys_diner.menu` table based on the `product_id` column.\n- In the outer query, calculate the points by using a `CASE` statement to determine the points based on our assumptions above. \n    - If the `product_name` is 'sushi', multiply the price by 2 and then by 10. For orders placed between `join_date` and `valid_date`, also multiply the price by 2 and then by 10. \n    - For all other products, multiply the price by 10.\n- Calculate the sum of points for each customer.\n\n#### Answer:\n| customer_id | total_points | \n| ----------- | ---------- |\n| A           | 1020 |\n| B           | 320 |\n\nFrom this Table, we can gather that:\n- Total points for Customer A is 1,020.\n- Total points for Customer B is 320.\n\n***\nThank you for following along through my showcase of SQL knowledge! \n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjawsee97%2F8-week-sql-challenge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjawsee97%2F8-week-sql-challenge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjawsee97%2F8-week-sql-challenge/lists"}