├── Case Study #1-Danny's Dinner └── README.md ├── Case Study #2 - Pizza Runner └── README.md ├── Case Study #3 - Foodie-Fi └── README.md ├── Case Study #4 - Data Bank └── README.md ├── Case Study #5 - Data Mart └── README.md ├── Case Study #6 - Clique Bait └── README.md ├── Case Study #7 - Balanced Tree Clothing Co └── README.md ├── Case Study #8 - Fresh Segments └── README.md └── README.md /Case Study #1-Danny's Dinner/README.md: -------------------------------------------------------------------------------- 1 | 2 |

Case Study #1 - Danny's Diner👨🏻‍🍳

3 | Coding 4 |

Contents

5 | 13 | 14 |

Introduction

15 |

In early 2021, Danny follows his passion for Japanese food and opens "Danny's Diner," a charming restaurant offering sushi, curry, and ramen. However, lacking data analysis expertise, the restaurant struggles to leverage the basic data collected during its initial months to make informed business decisions. Danny's Diner seeks assistance in using this data effectively to keep the restaurant thriving.

16 | 17 |

Problem Statement

18 |

Danny aims to utilize customer data to gain valuable insights into their visiting patterns, spending habits, and favorite menu items. By establishing a deeper connection with his customers, he can provide a more personalized experience for his loyal patrons. 19 | 20 | He plans to use these insights to make informed decisions about expanding the existing customer loyalty program. Additionally, Danny seeks assistance in generating basic datasets for his team to inspect the data conveniently, without requiring SQL expertise. 21 | 22 | Due to privacy concerns, he has shared a sample of his overall customer data, hoping it will be sufficient for you to create fully functional SQL queries to address his questions. 23 | 24 | The case study revolves around three key datasets: 25 | 26 | - Sales 27 | - Menu 28 | - Members

29 | 30 |

Entity Relationship Diagram

31 | Coding 32 | 33 | 34 |

Case Study Questions & Solutions

35 | 36 |
    37 | 38 |
  1. What is the total amount each customer spent at the restaurant?
  2. 39 | 40 | ```sql 41 | SELECT S.customer_id, SUM(M.price) AS total_amnt 42 | FROM sales S 43 | JOIN menu M ON S.product_id = M.product_id 44 | GROUP BY S.customer_id 45 | ORDER BY customer_id 46 | ``` 47 | 48 |
    Answer:
    49 | Coding 50 | 57 | 58 | 59 | 60 |
  3. How many days has each customer visited the restaurant?
  4. 61 | 62 | ```sql 63 | SELECT customer_id, COUNT(DISTINCT order_date) AS No_Days 64 | FROM sales 65 | GROUP BY customer_id 66 | ``` 67 |
    Answer:
    68 | Coding 69 | 76 | 77 | 78 | 79 |
  5. What was the first item from the menu purchased by each customer?
  6. 80 | 81 | ```sql 82 | WITH CTE AS 83 | (SELECT S.customer_id,DENSE_RANK() OVER(PARTITION BY S.customer_id ORDER BY S.order_date)AS rn,M.product_name 84 | FROM sales S 85 | JOIN menu M ON S.product_id=M.product_id) 86 | 87 | SELECT customer_id,product_name 88 | FROM CTE 89 | WHERE rn=1 90 | ``` 91 | 92 |
    Answer:
    93 | Coding 94 | 104 | 105 | 106 |
  7. What is the most purchased item on the menu and how many times was it purchased by all customers?
  8. 107 | 108 | ```sql 109 | SELECT M.product_name,COUNT(S.product_id)AS most_ordered 110 | FROM Sales S 111 | JOIN menu M ON S.product_id=M.product_id 112 | GROUP BY M.product_name 113 | ORDER BY most_ordered DESC 114 | LIMIT 1 115 | ``` 116 | 117 |
    Answer:
    118 | Coding 119 | 128 | 129 | 130 | 131 |
  9. Which item was the most popular for each customer?
  10. 132 | 133 | ```sql 134 | WITH CTE AS 135 | (SELECT S.customer_id,M.product_name,COUNT(M.product_id)AS order_count,DENSE_RANK() OVER(PARTITION BY S.customer_id ORDER BY COUNT(S.product_id)DESC) AS rnk 136 | FROM sales S 137 | JOIN menu M ON S.product_id=M.product_id 138 | GROUP BY S.customer_id,M.product_name) 139 | 140 | SELECT customer_id,product_name,order_count 141 | FROM CTE 142 | WHERE rnk=1 143 | ``` 144 | 145 |
    Answer:
    146 | Coding 147 | 159 | 160 | 161 |
  11. Which item was purchased first by the customer after they became a member?
  12. 162 | 163 | ```sql 164 | SELECT DISTINCT ON (s.customer_id) 165 | s.customer_id, 166 | m.product_name 167 | FROM sales s 168 | JOIN members mbr ON s.customer_id = mbr.customer_id 169 | JOIN menu m ON s.product_id = m.product_id 170 | WHERE s.order_date > mbr.join_date 171 | ORDER BY s.customer_id; 172 | ``` 173 | 174 |
    Answer:
    175 | Coding 176 | 187 | 188 | 189 |
  13. Which item was purchased just before the customer became a member?
  14. 190 | 191 | ```sql 192 | SELECT DISTINCT ON (s.customer_id) 193 | s.customer_id, 194 | m.product_name 195 | FROM sales s 196 | JOIN members mbr ON s.customer_id = mbr.customer_id 197 | JOIN menu m ON s.product_id = m.product_id 198 | WHERE s.order_date < mbr.join_date 199 | ORDER BY s.customer_id; 200 | ``` 201 | 202 |
    Answer:
    203 | Coding 204 | 215 | 216 | 217 |
  15. What is the total items and amount spent for each member before they became a member?
  16. 218 | 219 | ```sql 220 | SELECT S.customer_id, 221 | COUNT(S.product_id) AS total_item, 222 | SUM(M.price) AS total_amont 223 | FROM sales S 224 | JOIN menu M ON S.product_id=M.product_id 225 | JOIN members ME ON S.customer_id=ME.customer_id 226 | WHERE S.order_dateAnswer: 232 | Coding 233 | 244 | 245 | 246 |
  17. If each $1 spent equates to 10 points and sushi has a 2x points multiplier - how many points would each customer have?
  18. 247 | 248 | ```sql 249 | SELECT s.customer_id, 250 | SUM(CASE 251 | WHEN m.product_name = 'sushi' THEN price * 2 252 | ELSE price 253 | END) * 10 AS total_points 254 | FROM sales s 255 | JOIN menu m ON s.product_id = m.product_id 256 | GROUP BY s.customer_id 257 | ORDER BY s.customer_id; 258 | ``` 259 | 260 |
    Answer:
    261 | Coding 262 | 274 | 275 | 276 |
  19. 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?
  20. 277 | 278 | ```sql 279 | WITH dates_cte AS ( 280 | SELECT 281 | customer_id, 282 | join_date, 283 | join_date + INTERVAL '6 days' AS valid_date, 284 | DATE_TRUNC('month', '2021-01-31'::DATE) + INTERVAL '1 month' - INTERVAL '1 day' AS last_date 285 | FROM members 286 | ) 287 | 288 | SELECT 289 | s.customer_id, 290 | SUM(CASE 291 | WHEN m.product_name = 'sushi' OR (s.order_date BETWEEN dates.join_date AND dates.valid_date) THEN 2 * 10 * m.price 292 | ELSE 10 * m.price END) AS points 293 | FROM sales s 294 | INNER JOIN dates_cte AS dates 295 | ON s.customer_id = dates.customer_id 296 | AND dates.join_date <= s.order_date 297 | AND s.order_date <= dates.last_date 298 | INNER JOIN menu m 299 | ON s.product_id = m.product_id 300 | GROUP BY s.customer_id 301 | ORDER BY s.customer_id; 302 | ``` 303 | 304 |
    Answer:
    305 | Coding 306 |
307 | 321 | 322 | 323 |

Bonus Questions & Solutions

324 |
Join All The Things
325 | 326 | ```sql 327 | WITH customer_member_status AS ( 328 | SELECT 329 | s.customer_id, 330 | s.order_date, 331 | m.product_name, 332 | m.price, 333 | CASE 334 | WHEN mbr.join_date <= s.order_date THEN 'Y' 335 | ELSE 'N' 336 | END AS member 337 | FROM sales s 338 | INNER JOIN menu m ON s.product_id = m.product_id 339 | LEFT JOIN members mbr ON s.customer_id = mbr.customer_id 340 | ) 341 | SELECT 342 | customer_id, 343 | order_date, 344 | product_name, 345 | price, 346 | member 347 | FROM customer_member_status 348 | ORDER BY 349 | customer_id, 350 | member DESC, 351 | order_date; 352 | ``` 353 | 354 |
Answer:
355 | Coding 356 | 367 | 368 | 369 |
Rank All The Things
370 |

Danny needs additional information about the ranking of customer products. However, he specifically requires null ranking values for non-member purchases, as he is not interested in ranking customers who are not yet part of the loyalty program.

371 | 372 | ```sql 373 | WITH customers_data AS ( 374 | SELECT 375 | sales.customer_id, 376 | sales.order_date, 377 | menu.product_name, 378 | menu.price, 379 | CASE 380 | WHEN members.join_date > sales.order_date THEN 'N' 381 | WHEN members.join_date <= sales.order_date THEN 'Y' 382 | ELSE 'N' 383 | END AS member_status 384 | FROM sales 385 | LEFT JOIN members ON sales.customer_id = members.customer_id 386 | INNER JOIN menu ON sales.product_id = menu.product_id 387 | ) 388 | 389 | SELECT 390 | customer_id, 391 | order_date, 392 | product_name, 393 | price, 394 | member_status AS member, 395 | CASE 396 | WHEN member_status = 'N' THEN NULL 397 | ELSE RANK() OVER (PARTITION BY customer_id, member_status ORDER BY order_date) 398 | END AS ranking 399 | FROM customers_data; 400 | ``` 401 | 402 |
Answer:
403 | Coding 404 | 405 | 416 | 417 | 418 |

Key Insights

419 | 420 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | -------------------------------------------------------------------------------- /Case Study #3 - Foodie-Fi/README.md: -------------------------------------------------------------------------------- 1 |

Case Study #3 - Foodie-Fi🫕🥑

2 | Coding 3 |

Contents

4 | 5 | 18 | 19 |

Introduction

20 |

In response to the growing popularity of subscription-based businesses, Danny recognized a significant market gap. He saw an opportunity to introduce a distinctive streaming service, one that exclusively featured culinary content—a culinary counterpart to platforms like Netflix. With this vision in mind, Danny collaborated with a group of astute friends to establish Foodie-Fi, a startup launched in 2020. The company quickly began offering monthly and annual subscription plans, granting subscribers unrestricted access to an array of exclusive culinary videos sourced from across the globe.
21 | 22 | At the heart of Foodie-Fi's foundation lies Danny's commitment to data-driven decision-making. He was resolute in leveraging data to inform all future investments and innovative features. This case study delves into the realm of subscription-style digital data, where insights derived from data analysis are pivotal in addressing critical business inquiries and steering the company toward sustained growth and success.

23 | 24 |

Entity Relationship Diagram

25 | Coding 26 | 27 |

Case Study Questions & Solutions

28 | 29 |

A. Customer Journey🫕🥑

30 | 31 |
    32 |
  1. Based off the 8 sample customers provided in the sample from the subscriptions table, write a brief description about each customer’s onboarding journey.
  2. 33 | 34 | ```sql 35 | SELECT 36 | s.customer_id, 37 | p.plan_name, 38 | s.start_date 39 | FROM 40 | subscriptions s 41 | JOIN 42 | plans p ON s.plan_id = p.plan_id 43 | ORDER BY 44 | s.customer_id, s.start_date; 45 | ``` 46 | 47 |
    Answer:
    48 | Coding 49 |
50 | 51 |
    52 |
  1. 53 | Customer 1: 54 | 58 |
  2. 59 |
  3. 60 | Customer 2: 61 | 65 |
  4. 66 |
  5. 67 | Customer 11: 68 | 72 |
  6. 73 |
  7. 74 | Customer 13: 75 | 80 |
  8. 81 |
  9. 82 | Customer 15: 83 | 88 |
  10. 89 |
  11. 90 | Customer 16: 91 | 96 |
  12. 97 |
  13. 98 | Customer 18: 99 | 103 |
  14. 104 |
  15. 105 | Customer 19: 106 | 111 |
  16. 112 |
113 | 114 | 115 |

B. Data Analysis Questions📊

116 |
    117 |
  1. How many customers has Foodie-Fi ever had?
  2. 118 | 119 | ```sql 120 | SELECT COUNT(DISTINCT customer_id) AS customer_count 121 | FROM subscriptions 122 | ``` 123 |
    Answer:
    124 | Coding 125 | 130 | 131 | 132 |
  3. What is the monthly distribution of trial plan start_date values for our dataset - use the start of the month as the group by value
  4. 133 | 134 | ```sql 135 | SELECT 136 | DATE_TRUNC('month', start_date) AS month_start, 137 | COUNT(*) AS trial_starts 138 | FROM 139 | subscriptions 140 | WHERE 141 | plan_id = 0 142 | GROUP BY 143 | month_start 144 | ORDER BY 145 | month_start; 146 | ``` 147 |
    Answer:
    148 | Coding 149 | 158 | 159 | 160 |
  5. What plan start_date values occur after the year 2020 for our dataset? Show the breakdown by count of events for each plan_name
  6. 161 | 162 | ```sql 163 | SELECT 164 | p.plan_name, 165 | p.plan_id, 166 | COUNT(*) AS event_count 167 | FROM 168 | subscriptions s 169 | JOIN 170 | plans p ON s.plan_id = p.plan_id 171 | WHERE 172 | s.start_date > '2020-12-31' -- Filter for start dates after 2020 173 | GROUP BY 174 | p.plan_name, p.plan_id 175 | ORDER BY 176 | p.plan_name, p.plan_id; 177 | ``` 178 |
    Answer:
    179 | Coding 180 | 189 | 190 | 191 |
  7. What is the customer count and percentage of customers who have churned rounded to 1 decimal place?
  8. 192 | 193 | ```sql 194 | SELECT 195 | COUNT(DISTINCT CASE WHEN s.plan_id = 4 AND s.start_date <= CURRENT_DATE THEN s.customer_id END) AS churned_customers, 196 | ROUND(COUNT(DISTINCT CASE WHEN s.plan_id = 4 AND s.start_date <= CURRENT_DATE THEN s.customer_id END) * 100.0 / COUNT(DISTINCT s.customer_id), 1) AS churned_percentage 197 | FROM 198 | subscriptions s; 199 | ``` 200 |
    Answer:
    201 | Coding 202 | 209 | 210 | 211 |
  9. How many customers have churned straight after their initial free trial - what percentage is this rounded to the nearest whole number?
  10. 212 | 213 | ```sql 214 | WITH ranked_cte AS ( 215 | SELECT 216 | sub.customer_id, 217 | plans.plan_name, 218 | LEAD(plans.plan_name) OVER ( 219 | PARTITION BY sub.customer_id 220 | ORDER BY sub.start_date) AS next_plan 221 | FROM subscriptions AS sub 222 | JOIN plans 223 | ON sub.plan_id = plans.plan_id 224 | ) 225 | 226 | SELECT 227 | COUNT(customer_id) AS customers, 228 | ROUND(100.0 * 229 | COUNT(customer_id) 230 | / (SELECT COUNT(DISTINCT customer_id) 231 | FROM subscriptions) 232 | ) AS churn_percentage 233 | FROM ranked_cte 234 | WHERE plan_name = 'trial' 235 | AND next_plan = 'churn'; 236 | 237 | ``` 238 |
    Answer:
    239 | Coding 240 | 251 | 252 | 253 |
  11. What is the number and percentage of customer plans after their initial free trial?
  12. 254 | 255 | ```sql 256 | WITH next_plans AS ( 257 | SELECT 258 | customer_id, 259 | plan_id, 260 | LEAD(plan_id) OVER( 261 | PARTITION BY customer_id 262 | ORDER BY plan_id) as next_plan_id 263 | FROM subscriptions 264 | ) 265 | 266 | SELECT 267 | next_plan_id AS plan_id, 268 | COUNT(customer_id) AS after_free_customers, 269 | ROUND(100 * 270 | COUNT(customer_id)::NUMERIC 271 | / (SELECT COUNT(DISTINCT customer_id) 272 | FROM subscriptions) 273 | ,1) AS after_percentage 274 | FROM next_plans 275 | WHERE next_plan_id IS NOT NULL 276 | AND plan_id = 0 277 | GROUP BY next_plan_id 278 | ORDER BY next_plan_id; 279 | ``` 280 |
    Answer:
    281 | Coding 282 | 294 | 295 | 296 |
  13. What is the customer count and percentage breakdown of all 5 plan_name values at 2020-12-31?
  14. 297 | 298 | ```sql 299 | SELECT 300 | p.plan_name, 301 | COUNT(DISTINCT s.customer_id) AS customer_count, 302 | ROUND(100.0 * COUNT(DISTINCT s.customer_id) / (SELECT COUNT(DISTINCT customer_id) FROM subscriptions WHERE start_date <= '2020-12-31'), 1) AS percentage 303 | FROM 304 | subscriptions s 305 | JOIN 306 | plans p ON s.plan_id = p.plan_id 307 | WHERE 308 | s.start_date <= '2020-12-31' 309 | GROUP BY 310 | p.plan_name,p.plan_id 311 | ORDER BY 312 | p.plan_id; 313 | ```` 314 |
    Answer:
    315 | Coding 316 | 329 | 330 | 331 |
  15. How many customers have upgraded to an annual plan in 2020?
  16. 332 | 333 | ```sql 334 | SELECT 335 | COUNT(DISTINCT customer_id) AS upgraded_customers_count 336 | FROM 337 | subscriptions 338 | WHERE 339 | start_date >= '2020-01-01' 340 | AND start_date <= '2020-12-31' 341 | AND plan_id = 3; -- Plan ID 3 represents the annual pro plan 342 | ``` 343 |
    Answer:
    344 | Coding 345 | 352 | 353 | 354 |
  17. How many customers downgraded from a pro monthly to a basic monthly plan in 2020?
  18. 355 | 356 | ```sql 357 | SELECT COUNT(*) AS num_downgrades 358 | FROM subscriptions prev 359 | JOIN subscriptions current ON prev.customer_id = current.customer_id 360 | AND prev.plan_id = 2 -- Plan ID 2 represents pro monthly plan 361 | AND current.plan_id = 1 -- Plan ID 1 represents basic monthly plan 362 | AND prev.start_date <= current.start_date 363 | WHERE EXTRACT(YEAR FROM prev.start_date) = 2020; 364 | ``` 365 |
    Answer:
    366 | Coding 367 | 375 |
376 | 377 |

C. Challenge Payment Question💰

378 |
    379 |
  1. The Foodie-Fi team wants you to create a new payments table for the year 2020 that includes amounts paid by each customer in the subscriptions table with the following requirements: 380 |
      381 |
    • monthly payments always occur on the same day of month as the original start_date of any monthly paid plan
    • 382 |
    • upgrades from basic to monthly or pro plans are reduced by the current paid amount in that month and start immediately
    • 383 |
    • upgrades from pro monthly to pro annual are paid at the end of the current billing period and also starts at the end of the month period
    • 384 |
    • once a customer churns they will no longer make payments
  2. 385 | 386 | ```sql 387 | WITH all_plans AS ( 388 | SELECT 389 | s.customer_id, 390 | s.plan_id, 391 | p.plan_name, 392 | s.start_date AS plan_start_date, 393 | p.price, 394 | CASE 395 | WHEN p.plan_name LIKE 'pro monthly%' THEN 396 | DATE_TRUNC('month', s.start_date)::DATE 397 | ELSE 398 | CASE 399 | WHEN EXTRACT(MONTH FROM s.start_date) = 12 THEN s.start_date 400 | ELSE DATE_TRUNC('month', s.start_date + INTERVAL '1 month')::DATE 401 | END 402 | END AS payment_date 403 | FROM subscriptions s 404 | JOIN plans p ON s.plan_id = p.plan_id 405 | WHERE s.start_date >= '2020-01-01' AND s.start_date <= '2020-12-31' 406 | ) 407 | , payments AS ( 408 | SELECT 409 | customer_id, 410 | plan_id, 411 | plan_name, 412 | payment_date, 413 | price AS amount, 414 | ROW_NUMBER() OVER (PARTITION BY customer_id, plan_id, plan_name, payment_date ORDER BY plan_start_date) AS payment_order 415 | FROM all_plans 416 | ) 417 | -- Finalize the query 418 | SELECT 419 | customer_id, 420 | plan_id, 421 | plan_name, 422 | payment_date, 423 | amount, 424 | payment_order 425 | FROM payments 426 | WHERE payment_order = 1 OR (amount > 0 AND payment_order > 1) 427 | ORDER BY customer_id, plan_id, payment_date, payment_order 428 | LIMIT 20; 429 | ``` 430 |
    Answer:
    431 | Coding 432 | 444 |
445 | 446 | 447 | 448 | -------------------------------------------------------------------------------- /Case Study #4 - Data Bank/README.md: -------------------------------------------------------------------------------- 1 |

Case Study #4 - Data Bank🏦

2 | Coding 3 |

Contents

4 | 5 | 18 |

Introduction

19 |

Welcome to an enthralling journey into the world of finance, innovation, and data convergence. In this captivating case study project, we immerse ourselves in the realm of Neo-Banks, the trailblazing digital financial entities revolutionizing the industry landscape by eliminating physical branches. Our focus zooms in on an ingenious visionary named Danny, whose aspirations transcend the ordinary, leading to the inception of a remarkable initiative – "Data Bank."
20 | 21 | Within the fabric of this narrative lies a compelling fusion of Neo-Banking, cryptocurrency, and cutting-edge data management. The birth of Data Bank signifies a paradigm shift where the contours of digital banking intertwine seamlessly with the frontiers of secure distributed data storage.
22 | 23 | The essence of Data Bank mirrors that of traditional digital banks, albeit with an unprecedented twist. Not confined merely to financial transactions, this avant-garde establishment boasts the accolade of harboring the world's most impregnable distributed data storage platform. As we delve deeper, a unique interplay emerges – customers' cloud data storage allotments are intricately tied to their financial standing. Yet, the intricacies of this symbiotic relationship beckon us to explore further.
24 | 25 | Our protagonist, Data Bank, has set its sights on twin goals: expanding its customer base and, concurrently, gaining insights to navigate the data storage landscape. It is in this intricate tapestry of aspirations that we invite you, the analytical trailblazers, to join hands with the Data Bank team.
26 | 27 | This case study project is an expedition into the realms of metric calculation, growth strategy formulation, and incisive data-driven insights. As collaborators in this journey, we wield the tools of analysis to forecast and shape future developments. The canvas before us is one of intricate calculation, strategic expansion, and data-driven foresight. Embark on this expedition as we decipher the chronicles of Data Bank's evolution, where innovation intersects with pragmatism, and where data illuminates the path forward.

28 | 29 |

Entity Relationship Diagram

30 | Coding 31 |

Case Study Questions & Solutions

32 | 33 |

A. Customer Nodes Exploration👥

34 |
    35 |
  1. How many unique nodes are there on the Data Bank system?
  2. 36 | 37 | ```sql 38 | SELECT COUNT(DISTINCT node_id) AS unique_nodes_count 39 | FROM customer_nodes; 40 | ``` 41 |
    Answer:
    42 | Coding 43 | 48 | 49 | 50 |
  3. What is the number of nodes per region?
  4. 51 | 52 | ```sql 53 | SELECT r.region_name, COUNT(DISTINCT cn.node_id) AS nodes_per_region 54 | FROM regions r 55 | LEFT JOIN customer_nodes cn ON r.region_id = cn.region_id 56 | GROUP BY r.region_name 57 | ORDER BY nodes_per_region DESC; 58 | ``` 59 |
    Answer:
    60 | Coding 61 | 69 | 70 | 71 |
  5. How many customers are allocated to each region?
  6. 72 | 73 | ```sql 74 | SELECT r.region_name, COUNT(cn.customer_id) AS customers_per_region 75 | FROM regions r 76 | LEFT JOIN customer_nodes cn ON r.region_id = cn.region_id 77 | GROUP BY r.region_name 78 | ORDER BY customers_per_region DESC; 79 | ``` 80 |
    Answer:
    81 | Coding 82 | 90 | 91 | 92 |
  7. How many days on average are customers reallocated to a different node?
  8. 93 | 94 | ```sql 95 | WITH CTE AS 96 | (SELECT customer_id, 97 | node_id, 98 | end_date - start_date AS node_dys 99 | FROM customer_nodes 100 | WHERE end_date != '9999-12-31' 101 | GROUP BY customer_id, node_id, start_date, end_date), 102 | 103 | CTE2 AS 104 | ( 105 | SELECT customer_id,node_id, 106 | SUM(node_dys) AS total_node 107 | FROM CTE 108 | GROUP BY customer_id, node_id) 109 | 110 | SELECT ROUND(AVG(total_node)) AS avg_n 111 | FROM CTE2; 112 | ``` 113 |
    Answer:
    114 | Coding 115 | 122 | 123 | 124 |
  9. What is the median, 80th and 95th percentile for this same reallocation days metric for each region?
  10. 125 | 126 | ```sql 127 | WITH date_diff_cte AS ( 128 | SELECT 129 | cn.region_id, 130 | end_date - start_date AS node_dys 131 | FROM 132 | customer_nodes cn 133 | WHERE 134 | end_date != '9999-12-31' 135 | ) 136 | SELECT 137 | r.region_name, 138 | PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY node_dys) AS median, 139 | PERCENTILE_CONT(0.8) WITHIN GROUP (ORDER BY node_dys) AS percentile_80, 140 | PERCENTILE_CONT(0.95) WITHIN GROUP (ORDER BY node_dys) AS percentile_95 141 | FROM 142 | date_diff_cte d 143 | JOIN 144 | regions r ON d.region_id = r.region_id 145 | GROUP BY 146 | r.region_name; 147 | ``` 148 |
    Answer:
    149 | Coding 150 | 159 |
160 | 161 |

B. Customer Transactions💸

162 |
    163 |
  1. What is the unique count and total amount for each transaction type?
  2. 164 | 165 | ```sql 166 | SELECT 167 | txn_type AS transaction_type, 168 | COUNT(customer_id) AS tn_cnt, 169 | SUM(txn_amount) AS ttl_amnt 170 | FROM customer_transactions 171 | GROUP BY txn_type; 172 | ``` 173 | 174 |
    Answer:
    175 | Coding 176 | 184 | 185 | 186 |
  3. What is the average total historical deposit counts and amounts for all customers?
  4. 187 | 188 | ```sql 189 | WITH CTE AS ( 190 | SELECT 191 | customer_id, 192 | COUNT(customer_id) AS cnt, 193 | AVG(txn_amount) AS avg_amnt 194 | FROM customer_transactions 195 | WHERE txn_type = 'deposit' 196 | GROUP BY customer_id 197 | ) 198 | 199 | SELECT 200 | ROUND(AVG(cnt)) AS count_avgcnt, 201 | ROUND(AVG(avg_amnt)) AS amt_avgcnt 202 | FROM CTE; 203 | ``` 204 |
    Answer:
    205 | Coding 206 | 213 | 214 | 215 |
  5. For each month - how many Data Bank customers make more than 1 deposit and either 1 purchase or 1 withdrawal in a single month?
  6. 216 | 217 | ```sql 218 | WITH monthly_transactions AS ( 219 | SELECT 220 | customer_id, 221 | DATE_TRUNC('month', txn_date) AS transaction_month, 222 | SUM(CASE WHEN txn_type = 'deposit' THEN 0 ELSE 1 END) AS deposit_count, 223 | SUM(CASE WHEN txn_type = 'withdrawal' THEN 0 ELSE 1 END) AS purchase_count, 224 | SUM(CASE WHEN txn_type = 'withdrawal' THEN 1 ELSE 0 END) AS withdrawal_count 225 | FROM customer_transactions 226 | GROUP BY customer_id, DATE_TRUNC('month', txn_date) 227 | ) 228 | 229 | SELECT 230 | transaction_month AS mth, 231 | COUNT(DISTINCT customer_id) AS customer_count 232 | FROM monthly_transactions 233 | WHERE deposit_count > 1 234 | AND (purchase_count >= 1 OR withdrawal_count >= 1) 235 | GROUP BY transaction_month 236 | ORDER BY transaction_month; 237 | ``` 238 |
    Answer:
    239 | Coding 240 | 250 | 251 | 252 |
  7. What is the closing balance for each customer at the end of the month?
  8. 253 | 254 | ```sql 255 | WITH customer_monthly_balances AS ( 256 | SELECT 257 | customer_id, 258 | DATE_TRUNC('month', txn_date) AS transaction_month, 259 | SUM(CASE WHEN txn_type = 'deposit' THEN txn_amount ELSE 0 END) - 260 | SUM(CASE WHEN txn_type IN ('purchase', 'withdrawal') THEN txn_amount ELSE 0 END) AS closing_balance 261 | FROM customer_transactions 262 | GROUP BY customer_id, transaction_month 263 | ) 264 | 265 | SELECT 266 | customer_id, 267 | transaction_month, 268 | closing_balance 269 | FROM customer_monthly_balances 270 | ORDER BY customer_id, transaction_month; 271 | ``` 272 |
    Answer:
    273 | Coding 274 | 282 | 283 | 284 |
  9. What is the percentage of customers who increase their closing balance by more than 5%?
  10. 285 | 286 | ```sql 287 | WITH customer_monthly_balances AS ( 288 | SELECT 289 | customer_id, 290 | DATE_TRUNC('month', txn_date) AS transaction_month, 291 | SUM(CASE WHEN txn_type = 'deposit' THEN txn_amount ELSE 0 END) - 292 | SUM(CASE WHEN txn_type IN ('purchase', 'withdrawal') THEN txn_amount ELSE 0 END) AS closing_balance 293 | FROM customer_transactions 294 | GROUP BY customer_id, transaction_month 295 | ) 296 | SELECT 297 | ROUND( 298 | (COUNT(*) FILTER (WHERE closing_balance_increase > 5) * 100.0) / COUNT(*), 299 | 2 300 | ) AS percentage_increase 301 | FROM ( 302 | SELECT 303 | customer_id, 304 | transaction_month, 305 | closing_balance, 306 | LAG(closing_balance) OVER (PARTITION BY customer_id ORDER BY transaction_month) AS prev_balance, 307 | (closing_balance - LAG(closing_balance) OVER (PARTITION BY customer_id ORDER BY transaction_month)) * 100.0 / NULLIF(LAG(closing_balance) OVER (PARTITION BY customer_id ORDER BY transaction_month), 0) AS closing_balance_increase 308 | FROM customer_monthly_balances 309 | ) AS balance_changes; 310 | ``` 311 |
    Answer:
    312 | Coding 313 | 324 |
325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /Case Study #5 - Data Mart/README.md: -------------------------------------------------------------------------------- 1 |

Case Study #5 - Data Mart🛒

2 | Coding 3 |

Contents

4 | 5 | 17 | 18 |

Introduction

19 |

In the focal point of our case study is Danny's latest enterprise, Data Mart, which emerges following his successful oversight of global operations for an online grocery store specializing in fresh produce. Danny now seeks our collaboration to dissect his sales performance analysis.
20 | 21 | In the juncture of June 2020, Data Mart underwent significant supply chain modifications. Embracing sustainability, the company transitioned all its products to employ eco-friendly packaging throughout the entire journey from the farm to the end consumer.
22 | 23 | Danny is enlisting our expertise to quantify the ramifications of this alteration on Data Mart's sales performance across its distinct business sectors.
24 | 25 | Central to this inquiry are the subsequent pivotal questions:
26 |

Using a single SQL query - create a new output table which has the following details:
224 |
229 | 230 | ```sql 231 | WITH ProdView AS ( 232 | SELECT 233 | e.visit_id, 234 | ph.product_id, 235 | ph.page_name AS product_name, 236 | ph.product_category, 237 | COUNT(CASE WHEN e.event_type = 1 THEN 1 ELSE NULL END) AS views 238 | FROM events AS e 239 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 240 | WHERE product_id IS NOT NULL 241 | GROUP BY e.visit_id, ph.product_id, ph.page_name, ph.product_category 242 | ), 243 | ProdCart AS ( 244 | SELECT 245 | e.visit_id, 246 | ph.product_id, 247 | COUNT(CASE WHEN e.event_type = 2 THEN 1 ELSE NULL END) AS cart_adds 248 | FROM events AS e 249 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 250 | WHERE product_id IS NOT NULL 251 | GROUP BY e.visit_id, ph.product_id 252 | ), 253 | PurchaseEvents AS ( 254 | SELECT DISTINCT visit_id 255 | FROM events 256 | WHERE event_type = 3 257 | ), 258 | ProductStats AS ( 259 | SELECT 260 | pvc.visit_id, 261 | pvc.product_id, 262 | pvc.product_name, 263 | pvc.product_category, 264 | pvc.views, 265 | pcc.cart_adds, 266 | CASE WHEN pe.visit_id IS NOT NULL THEN 1 ELSE 0 END AS purchases 267 | FROM ProdView AS pvc 268 | JOIN ProdCart AS pcc ON pvc.visit_id = pcc.visit_id AND pvc.product_id = pcc.product_id 269 | LEFT JOIN PurchaseEvents AS pe ON pvc.visit_id = pe.visit_id 270 | ) 271 | SELECT 272 | product_name, 273 | product_category, 274 | SUM(views) AS total_views, 275 | SUM(cart_adds) AS total_cart_adds, 276 | SUM(CASE WHEN cart_adds > 0 AND purchases = 0 THEN 1 ELSE 0 END) AS abandoned, 277 | SUM(CASE WHEN cart_adds = 1 AND purchases = 1 THEN 1 ELSE 0 END) AS purchases 278 | FROM ProductStats 279 | GROUP BY product_name, product_category 280 | ORDER BY product_name; 281 | ``` 282 | 283 |
Answer:
284 | Coding 285 | 286 | 298 | 299 | 300 | Additionally, create another table which further aggregates the data for the above points but this time for each product category instead of individual products
301 | 302 | ```sql 303 | WITH ProductPageEvents AS ( 304 | SELECT 305 | e.visit_id, 306 | ph.product_id, 307 | ph.page_name AS product_name, 308 | ph.product_category, 309 | COUNT(CASE WHEN e.event_type = 1 THEN 1 ELSE NULL END) AS page_view, 310 | COUNT(CASE WHEN e.event_type = 2 THEN 1 ELSE NULL END) AS cart_add 311 | FROM events AS e 312 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 313 | WHERE product_id IS NOT NULL 314 | GROUP BY e.visit_id, ph.product_id, ph.page_name, ph.product_category 315 | ), 316 | PurchaseEvents AS ( 317 | SELECT DISTINCT visit_id 318 | FROM events 319 | WHERE event_type = 3 320 | ), 321 | CombinedTable AS ( 322 | SELECT 323 | ppe.visit_id, 324 | ppe.product_id, 325 | ppe.product_name, 326 | ppe.product_category, 327 | ppe.page_view, 328 | ppe.cart_add, 329 | CASE WHEN pe.visit_id IS NOT NULL THEN 1 ELSE 0 END AS purchase 330 | FROM ProductPageEvents AS ppe 331 | LEFT JOIN PurchaseEvents AS pe ON ppe.visit_id = pe.visit_id 332 | ), 333 | ProductInfo AS ( 334 | SELECT 335 | product_name, 336 | product_category, 337 | SUM(page_view) AS views, 338 | SUM(cart_add) AS cart_adds, 339 | SUM(CASE WHEN cart_add = 1 AND purchase = 0 THEN 1 ELSE 0 END) AS abandoned, 340 | SUM(CASE WHEN cart_add = 1 AND purchase = 1 THEN 1 ELSE 0 END) AS purchases 341 | FROM CombinedTable 342 | GROUP BY product_id, product_name, product_category 343 | ), 344 | CategoryStats AS ( 345 | SELECT 346 | product_category, 347 | SUM(views) AS total_category_views, 348 | SUM(cart_adds) AS total_category_cart_adds, 349 | SUM(abandoned) AS total_category_abandoned, 350 | SUM(purchases) AS total_category_purchases 351 | FROM ProductInfo 352 | GROUP BY product_category 353 | ) 354 | 355 | 356 | SELECT 357 | product_category, 358 | total_category_views, 359 | total_category_cart_adds, 360 | total_category_abandoned, 361 | total_category_purchases 362 | FROM CategoryStats; 363 | ``` 364 |
Answer:
365 | Coding 366 | 379 | 380 | 381 | Use your 2 new output tables - answer the following questions:

382 |
  • Which product had the most views, cart adds and purchases?
  • 383 | 384 | ```sql 385 | WITH ProductPageEvents AS ( 386 | SELECT 387 | e.visit_id, 388 | ph.product_id, 389 | ph.page_name AS product_name, 390 | ph.product_category, 391 | COUNT(CASE WHEN e.event_type = 1 THEN 1 ELSE NULL END) AS page_view, 392 | COUNT(CASE WHEN e.event_type = 2 THEN 1 ELSE NULL END) AS cart_add 393 | FROM events AS e 394 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 395 | WHERE product_id IS NOT NULL 396 | GROUP BY e.visit_id, ph.product_id, ph.page_name, ph.product_category 397 | ), 398 | PurchaseEvents AS ( 399 | SELECT DISTINCT visit_id 400 | FROM events 401 | WHERE event_type = 3 402 | ), 403 | CombinedTable AS ( 404 | SELECT 405 | ppe.visit_id, 406 | ppe.product_id, 407 | ppe.product_name, 408 | ppe.product_category, 409 | ppe.page_view, 410 | ppe.cart_add, 411 | CASE WHEN pe.visit_id IS NOT NULL THEN 1 ELSE 0 END AS purchase 412 | FROM ProductPageEvents AS ppe 413 | LEFT JOIN PurchaseEvents AS pe ON ppe.visit_id = pe.visit_id 414 | ), 415 | ProductInfo AS ( 416 | SELECT 417 | product_name, 418 | product_category, 419 | SUM(page_view) AS views, 420 | SUM(cart_add) AS cart_adds, 421 | SUM(CASE WHEN cart_add = 1 AND purchase = 0 THEN 1 ELSE 0 END) AS abandoned, 422 | SUM(CASE WHEN cart_add = 1 AND purchase = 1 THEN 1 ELSE 0 END) AS purchases 423 | FROM CombinedTable 424 | GROUP BY product_id, product_name, product_category 425 | ) 426 | 427 | SELECT 428 | product_name, 429 | MAX(views) AS most_views, 430 | MAX(cart_adds) AS most_cart_adds, 431 | MAX(purchases) AS most_purchases 432 | FROM ProductInfo 433 | GROUP BY product_name 434 | ORDER BY most_views DESC, most_cart_adds DESC, most_purchases DESC 435 | LIMIT 1; 436 | ``` 437 |
    Answer:
    438 | Coding 439 | 453 | 454 | 455 |
  • Which product was most likely to be abandoned?
  • 456 | 457 | ```sql 458 | WITH ProductPageEvents AS ( 459 | SELECT 460 | e.visit_id, 461 | ph.product_id, 462 | ph.page_name AS product_name, 463 | ph.product_category, 464 | COUNT(CASE WHEN e.event_type = 1 THEN 1 ELSE NULL END) AS page_view, 465 | COUNT(CASE WHEN e.event_type = 2 THEN 1 ELSE NULL END) AS cart_add 466 | FROM events AS e 467 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 468 | WHERE product_id IS NOT NULL 469 | GROUP BY e.visit_id, ph.product_id, ph.page_name, ph.product_category 470 | ), 471 | PurchaseEvents AS ( 472 | SELECT DISTINCT visit_id 473 | FROM events 474 | WHERE event_type = 3 475 | ), 476 | CombinedTable AS ( 477 | SELECT 478 | ppe.visit_id, 479 | ppe.product_id, 480 | ppe.product_name, 481 | ppe.product_category, 482 | ppe.page_view, 483 | ppe.cart_add, 484 | CASE WHEN pe.visit_id IS NOT NULL THEN 1 ELSE 0 END AS purchase 485 | FROM ProductPageEvents AS ppe 486 | LEFT JOIN PurchaseEvents AS pe ON ppe.visit_id = pe.visit_id 487 | ), 488 | ProductInfo AS ( 489 | SELECT 490 | product_name, 491 | product_category, 492 | SUM(page_view) AS views, 493 | SUM(cart_add) AS cart_adds, 494 | SUM(CASE WHEN cart_add = 1 AND purchase = 0 THEN 1 ELSE 0 END) AS abandoned, 495 | SUM(CASE WHEN cart_add = 1 AND purchase = 1 THEN 1 ELSE 0 END) AS purchases 496 | FROM CombinedTable 497 | GROUP BY product_id, product_name, product_category 498 | ) 499 | 500 | SELECT 501 | product_name, 502 | MAX(abandoned_percentage) AS most_likely_abandoned 503 | FROM ( 504 | SELECT 505 | product_name, 506 | (CAST(abandoned AS decimal) / CAST(cart_adds AS decimal)) * 100 AS abandoned_percentage 507 | FROM ProductInfo 508 | ) AS AbandonedPercentage 509 | GROUP BY product_name 510 | ORDER BY most_likely_abandoned DESC 511 | LIMIT 1; 512 | ``` 513 |
    Answer:
    514 | Coding 515 | 531 | 532 | 533 |
  • Which product had the highest view to purchase percentage?
  • 534 | 535 | ```sql 536 | WITH ProductPageEvents AS ( 537 | SELECT 538 | e.visit_id, 539 | ph.product_id, 540 | ph.page_name AS product_name, 541 | ph.product_category, 542 | COUNT(CASE WHEN e.event_type = 1 THEN 1 ELSE NULL END) AS page_view, 543 | COUNT(CASE WHEN e.event_type = 2 THEN 1 ELSE NULL END) AS cart_add 544 | FROM events AS e 545 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 546 | WHERE product_id IS NOT NULL 547 | GROUP BY e.visit_id, ph.product_id, ph.page_name, ph.product_category 548 | ), 549 | PurchaseEvents AS ( 550 | SELECT DISTINCT visit_id 551 | FROM events 552 | WHERE event_type = 3 553 | ), 554 | CombinedTable AS ( 555 | SELECT 556 | ppe.visit_id, 557 | ppe.product_id, 558 | ppe.product_name, 559 | ppe.product_category, 560 | ppe.page_view, 561 | ppe.cart_add, 562 | CASE WHEN pe.visit_id IS NOT NULL THEN 1 ELSE 0 END AS purchase 563 | FROM ProductPageEvents AS ppe 564 | LEFT JOIN PurchaseEvents AS pe ON ppe.visit_id = pe.visit_id 565 | ), 566 | ProductInfo AS ( 567 | SELECT 568 | product_name, 569 | product_category, 570 | SUM(page_view) AS views, 571 | SUM(cart_add) AS cart_adds, 572 | SUM(CASE WHEN cart_add = 1 AND purchase = 0 THEN 1 ELSE 0 END) AS abandoned, 573 | SUM(CASE WHEN cart_add = 1 AND purchase = 1 THEN 1 ELSE 0 END) AS purchases 574 | FROM CombinedTable 575 | GROUP BY product_id, product_name, product_category 576 | ), 577 | ViewToPurchase AS ( 578 | SELECT 579 | product_name, 580 | (CAST(views AS decimal) / CAST(purchases AS decimal)) * 100 AS view_to_purchase_percentage 581 | FROM ProductInfo 582 | ) 583 | 584 | SELECT 585 | product_name 586 | FROM ViewToPurchase 587 | ORDER BY view_to_purchase_percentage DESC 588 | LIMIT 1; 589 | ``` 590 |
    Answer:
    591 | Coding 592 | 607 | 608 | 609 |
  • What is the average conversion rate from view to cart add?
  • 610 | 611 | ```sql 612 | WITH ProductPageEvents AS ( 613 | SELECT 614 | e.visit_id, 615 | ph.product_id, 616 | ph.page_name AS product_name, 617 | ph.product_category, 618 | COUNT(CASE WHEN e.event_type = 1 THEN 1 ELSE NULL END) AS page_view, 619 | COUNT(CASE WHEN e.event_type = 2 THEN 1 ELSE NULL END) AS cart_add 620 | FROM events AS e 621 | JOIN page_hierarchy AS ph ON e.page_id = ph.page_id 622 | WHERE product_id IS NOT NULL 623 | GROUP BY e.visit_id, ph.product_id, ph.page_name, ph.product_category 624 | ), 625 | ProductStats AS ( 626 | SELECT 627 | product_name, 628 | SUM(page_view) AS views, 629 | SUM(cart_add) AS cart_adds 630 | FROM ProductPageEvents 631 | GROUP BY product_name 632 | ) 633 | 634 | SELECT 635 | AVG((CAST(cart_adds AS decimal) / CAST(views AS decimal)) * 100) AS average_conversion_rate 636 | FROM ProductStats; 637 | ``` 638 |
    Answer:
    639 | Coding 640 | 650 | 651 | 652 |

    C. Campaigns Analysis

    653 |
      654 |
    1. Generate a table that has 1 single row for every unique visit_id record and has the following columns: 655 |
        656 |
      • user_id
      • 657 |
      • visit_id
      • 658 |
      • visit_start_time: the earliest event_time for each visit
      • 659 |
      • page_views: count of page views for each visit
      • 660 |
      • cart_adds: count of product cart add events for each visit
      • 661 |
      • purchase: 1/0 flag if a purchase event exists for each visit
      • 662 |
      • campaign_name: map the visit to a campaign if the visit_start_time falls between the start_date and end_date
      • 663 |
      • impression: count of ad impressions for each visit
      • 664 |
      • click: count of ad clicks for each visit
      • 665 |
      • (Optional column) cart_products: a comma separated text value with products added to the cart sorted by the order they were added to the cart (hint: use the sequence_number)
    2. 666 | 667 | ```sql 668 | SELECT 669 | u.user_id, 670 | e.visit_id, 671 | MIN(e.event_time) AS visit_start_time, 672 | SUM(CASE WHEN e.event_type = 1 THEN 1 ELSE 0 END) AS page_views, 673 | SUM(CASE WHEN e.event_type = 2 THEN 1 ELSE 0 END) AS cart_adds, 674 | MAX(CASE WHEN e.event_type = 3 THEN 1 ELSE 0 END) AS purchase, 675 | ci.campaign_name, 676 | SUM(CASE WHEN e.event_type = 4 THEN 1 ELSE 0 END) AS impression, 677 | SUM(CASE WHEN e.event_type = 5 THEN 1 ELSE 0 END) AS click, 678 | STRING_AGG( 679 | CASE WHEN e.event_type = 2 THEN ph.page_name END, 680 | ', ' 681 | ORDER BY e.sequence_number 682 | ) AS cart_products 683 | FROM users u 684 | INNER JOIN events e ON u.cookie_id = e.cookie_id 685 | LEFT JOIN campaign_identifier ci ON e.event_time BETWEEN ci.start_date AND ci.end_date 686 | LEFT JOIN page_hierarchy ph ON e.page_id = ph.page_id 687 | GROUP BY u.user_id, e.visit_id, ci.campaign_name; 688 | 689 | ``` 690 |
      Answer:
      691 | Coding 692 | 704 |
    705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | -------------------------------------------------------------------------------- /Case Study #7 - Balanced Tree Clothing Co/README.md: -------------------------------------------------------------------------------- 1 |

    Case Study #7 - Balanced Tree Clothing Co.👚🧶

    2 | Coding 3 |

    Contents

    4 | 5 | 18 |

    Introduction

    19 |

    In this case study, we delve into the operations of Balanced Tree Clothing Company, a leading fashion enterprise renowned for curating a meticulously tailored selection of apparel and lifestyle gear designed for contemporary explorers. At the helm is Danny, the visionary CEO, who has enlisted our expertise in scrutinizing their sales accomplishments and creating a fundamental financial synopsis destined to be disseminated across the organization. This analysis offers valuable insights into their business strategies and performance metrics.

    20 | 21 |

    Entity Relationship Diagram

    22 | Coding 23 |

    Case Study Questions & Solutions

    24 | 25 |

    A. High Level Sales Analysis

    26 |
      27 |
    1. What was the total quantity sold for all products?
    2. 28 | 29 | ```sql 30 | SELECT COUNT(DISTINCT txn_id) AS unique_transactions 31 | FROM balanced_tree.sales; 32 | ``` 33 |
      Answer:
      34 | Coding 35 | 40 | 41 | 42 |
    3. What is the total generated revenue for all products before discounts?
    4. 43 | 44 | ```sql 45 | SELECT AVG(avg_unique_products) AS average_unique_products_per_transaction 46 | FROM ( 47 | SELECT txn_id, COUNT(DISTINCT prod_id) AS avg_unique_products 48 | FROM balanced_tree.sales 49 | GROUP BY txn_id 50 | ) AS unique_products_per_transaction; 51 | ``` 52 |
      Answer:
      53 | Coding 54 | 60 | 61 | 62 |
    5. What was the total discount amount for all products?
    6. 63 | 64 | ```sql 65 | SELECT SUM((price * qty) - (price * qty * (discount / 100))) AS total_discount_amount 66 | FROM balanced_tree.sales; 67 | 68 | ``` 69 |
      Answer:
      70 | Coding 71 | 78 | 79 |
    80 | 81 |

    B. Transaction Analysis

    82 |
      83 |
    1. How many unique transactions were there?
    2. 84 | 85 | ```sql 86 | SELECT COUNT(DISTINCT txn_id) AS unique_transactions 87 | FROM balanced_tree.sales; 88 | ``` 89 |
      Answer:
      90 | Coding 91 | 96 | 97 | 98 |
    3. What is the average unique products purchased in each transaction?
    4. 99 | 100 | ```sql 101 | SELECT AVG(avg_unique_products) AS average_unique_products_per_transaction 102 | FROM ( 103 | SELECT txn_id, COUNT(DISTINCT prod_id) AS avg_unique_products 104 | FROM balanced_tree.sales 105 | GROUP BY txn_id 106 | ) AS unique_products_per_transaction; 107 | ``` 108 |
      Answer:
      109 | Coding 110 | 116 | 117 | 118 |
    5. What are the 25th, 50th and 75th percentile values for the revenue per transaction?
    6. 119 | 120 | ```sql 121 | SELECT 122 | PERCENTILE_CONT(0.25) WITHIN GROUP (ORDER BY revenue) AS percentile_25th, 123 | PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY revenue) AS percentile_50th, 124 | PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY revenue) AS percentile_75th 125 | FROM ( 126 | SELECT 127 | txn_id, 128 | SUM(price * qty) AS revenue 129 | FROM balanced_tree.sales 130 | GROUP BY txn_id 131 | ) AS revenue_cte; 132 | ``` 133 |
      Answer:
      134 | Coding 135 | 141 | 142 | 143 |
    7. What is the average discount value per transaction?
    8. 144 | 145 | ```sql 146 | SELECT 147 | ROUND(SUM(qty * price * discount/100) / COUNT(DISTINCT txn_id)) AS avg_discount 148 | FROM balanced_tree.sales; 149 | ``` 150 |
      Answer:
      151 | Coding 152 | 158 | 159 | 160 |
    9. What is the percentage split of all transactions for members vs non-members?
    10. 161 | 162 | ```sql 163 | SELECT 164 | CASE 165 | WHEN member = 't' THEN 'Member' 166 | WHEN member = 'f' THEN 'Non-Member' 167 | END AS member_status, 168 | COUNT(txn_id) AS transaction_count, 169 | ROUND(100 * COUNT(txn_id) / (SELECT COUNT(txn_id) FROM balanced_tree.sales), 2) AS percentage 170 | FROM balanced_tree.sales 171 | GROUP BY member_status; 172 | ``` 173 |
      Answer:
      174 | Coding 175 | 183 | 184 | 185 |
    11. What is the average revenue for member transactions and non-member transactions?
    12. 186 | 187 | ```sql 188 | SELECT 189 | CASE 190 | WHEN member = 't' THEN 'Member' 191 | WHEN member = 'f' THEN 'Non-Member' 192 | END AS member_status, 193 | ROUND(AVG(price * qty), 2) AS avg_revenue 194 | FROM balanced_tree.sales 195 | GROUP BY member_status; 196 | ``` 197 |
      Answer:
      198 | Coding 199 | 206 |
    207 | 208 |

    C. Product Analysis

    209 |
      210 |
    1. What are the top 3 products by total revenue before discount?
    2. 211 | 212 | ```sql 213 | SELECT 214 | pd.product_id, 215 | pd.product_name, 216 | SUM(s.price * s.qty) AS total_revenue_before_discount 217 | FROM balanced_tree.product_details pd 218 | JOIN balanced_tree.sales s ON pd.product_id = s.prod_id 219 | GROUP BY pd.product_id, pd.product_name 220 | ORDER BY total_revenue_before_discount DESC 221 | LIMIT 3; 222 | ``` 223 |
      Answer:
      224 | Coding 225 | 234 | 235 | 236 |
    3. What is the total quantity, revenue and discount for each segment?
    4. 237 | 238 | ```sql 239 | SELECT 240 | pd.segment_name, 241 | SUM(s.qty) AS total_quantity, 242 | SUM(s.price * s.qty) AS total_revenue, 243 | SUM(s.qty * s.price * s.discount / 100) AS total_discount 244 | FROM balanced_tree.product_details pd 245 | JOIN balanced_tree.sales s ON pd.product_id = s.prod_id 246 | GROUP BY pd.segment_name 247 | ORDER BY total_revenue DESC; 248 | ``` 249 |
      Answer:
      250 | Coding 251 | 259 | 260 | 261 |
    5. What is the total quantity, revenue and discount for each segment?
    6. 262 | 263 | ```sql 264 | WITH top_selling_products AS ( 265 | SELECT 266 | pd.segment_id, 267 | pd.segment_name, 268 | pd.product_id, 269 | pd.product_name, 270 | SUM(s.qty) AS total_quantity, 271 | ROW_NUMBER() OVER (PARTITION BY pd.segment_id ORDER BY SUM(s.qty) DESC) AS rank 272 | FROM balanced_tree.product_details pd 273 | JOIN balanced_tree.sales s ON pd.product_id = s.prod_id 274 | GROUP BY pd.segment_id, pd.segment_name, pd.product_id, pd.product_name 275 | ) 276 | SELECT 277 | segment_id, 278 | segment_name, 279 | product_id, 280 | product_name, 281 | total_quantity 282 | FROM top_selling_products 283 | WHERE rank = 1; 284 | ``` 285 |
      Answer:
      286 | Coding 287 | 297 | 298 | 299 |
    7. What is the total quantity, revenue and discount for each category?
    8. 300 | 301 | ```sql 302 | SELECT 303 | pd.category_id, 304 | pd.category_name, 305 | SUM(s.qty) AS total_quantity, 306 | SUM(s.qty * s.price) AS total_revenue, 307 | SUM(s.qty * s.price * s.discount / 100) AS total_discount 308 | FROM balanced_tree.product_details pd 309 | JOIN balanced_tree.sales s ON pd.product_id = s.prod_id 310 | GROUP BY pd.category_id, pd.category_name; 311 | ``` 312 |
      Answer:
      313 | Coding 314 | 325 | 326 | 327 |
    9. What is the top selling product for each category?
    10. 328 | 329 | ```sql 330 | WITH top_selling_cte AS ( 331 | SELECT 332 | pd.category_id, 333 | pd.category_name, 334 | pd.product_id, 335 | pd.product_name, 336 | SUM(s.qty) AS total_quantity, 337 | RANK() OVER ( 338 | PARTITION BY pd.category_id 339 | ORDER BY SUM(s.qty) DESC) AS ranking 340 | FROM balanced_tree.product_details pd 341 | JOIN balanced_tree.sales s ON pd.product_id = s.prod_id 342 | GROUP BY 343 | pd.category_id, pd.category_name, pd.product_id, pd.product_name 344 | ) 345 | 346 | SELECT 347 | category_id, 348 | category_name, 349 | product_id, 350 | product_name, 351 | total_quantity 352 | FROM top_selling_cte 353 | WHERE ranking = 1; 354 | ``` 355 |
      Answer:
      356 | Coding 357 | 368 | 369 | 370 |
    11. What is the percentage split of revenue by product for each segment?
    12. 371 | 372 | ```sql 373 | WITH segment_revenue AS ( 374 | SELECT 375 | p.segment_id, 376 | p.segment_name, 377 | s.prod_id, 378 | p.product_name, 379 | SUM(s.price * s.qty) AS total_revenue 380 | FROM balanced_tree.sales s 381 | JOIN balanced_tree.product_details p ON s.prod_id = p.product_id 382 | GROUP BY 383 | p.segment_id, p.segment_name, s.prod_id, p.product_name 384 | ) 385 | 386 | SELECT 387 | sr.segment_id, 388 | sr.segment_name, 389 | sr.prod_id, 390 | sr.product_name, 391 | sr.total_revenue, 392 | ROUND(100 * sr.total_revenue / SUM(sr.total_revenue) OVER (PARTITION BY sr.segment_id), 2) AS revenue_percentage 393 | FROM segment_revenue sr; 394 | ``` 395 |
      Answer:
      396 | Coding 397 | 409 | 410 | 411 |
    13. What is the percentage split of revenue by segment for each category?
    14. 412 | 413 | ```sql 414 | WITH category_segment_revenue AS ( 415 | SELECT 416 | p.category_id, 417 | p.category_name, 418 | p.segment_id, 419 | p.segment_name, 420 | SUM(s.price * s.qty) AS total_revenue 421 | FROM balanced_tree.sales s 422 | JOIN balanced_tree.product_details p ON s.prod_id = p.product_id 423 | GROUP BY 424 | p.category_id, p.category_name, p.segment_id, p.segment_name 425 | ) 426 | 427 | SELECT 428 | csr.category_id, 429 | csr.category_name, 430 | csr.segment_id, 431 | csr.segment_name, 432 | csr.total_revenue, 433 | ROUND(100 * csr.total_revenue / SUM(csr.total_revenue) OVER (PARTITION BY csr.category_id), 2) AS revenue_percentage 434 | FROM category_segment_revenue csr; 435 | ``` 436 |
      Answer:
      437 | Coding 438 | 450 | 451 | 452 |
    15. What is the percentage split of total revenue by category?
    16. 453 | 454 | ```sql 455 | WITH category_revenue AS ( 456 | SELECT 457 | p.category_id, 458 | p.category_name, 459 | SUM(s.price * s.qty) AS total_revenue 460 | FROM balanced_tree.sales s 461 | JOIN balanced_tree.product_details p ON s.prod_id = p.product_id 462 | GROUP BY 463 | p.category_id, p.category_name 464 | ) 465 | 466 | SELECT 467 | cr.category_id, 468 | cr.category_name, 469 | cr.total_revenue, 470 | ROUND(100 * cr.total_revenue / SUM(cr.total_revenue) OVER (), 2) AS revenue_percentage 471 | FROM category_revenue cr; 472 | ``` 473 |
      Answer:
      474 | Coding 475 | 487 |
    488 | 489 | 490 | -------------------------------------------------------------------------------- /Case Study #8 - Fresh Segments/README.md: -------------------------------------------------------------------------------- 1 |

    Case Study #8 - Fresh Segments👨🏼‍💻

    2 | Coding 3 |

    Contents

    4 | 5 | 16 | 17 |

    Introduction

    18 |

    Discover the transformative journey of Fresh Segments, a pioneering digital marketing agency founded by Danny. By decoding online ad click behavior trends tailored to individual businesses, Fresh Segments empowers companies to understand their customer base like never before.
    19 | 20 | In this case study, we delve into Fresh Segments' innovative methodology. Clients entrust their customer lists to Fresh Segments, which then compiles and analyzes interest metrics, creating a comprehensive dataset for detailed examination.
    21 | 22 | The agency's forte lies in unraveling interest composition and rankings for each client, spotlighting the proportions of customers interacting with specific online assets. These insights, presented monthly, offer a holistic view of evolving customer interests.
    23 | 24 | Danny seeks our expertise in deciphering aggregated metrics for a sample client. Our mission is to distill key insights from this data, shedding light on customer lists and the array of captivating interests. Through this analysis, we illuminate overarching patterns, offering strategic guidance to propel Fresh Segments forward.

    25 | 26 |

    Case Study Questions & Solutions

    27 | 28 |

    A. Data Exploration and Cleansing

    29 |
      30 |
    1. Update the fresh_segments.interest_metrics table by modifying the month_year column to be a date data type with the start of the month
    2. 31 | 32 | ```sql 33 | alter table interest_metrics 34 | drop column month_year 35 | ``` 36 | ```sql 37 | alter table interest_metrics 38 | add month_year date 39 | ``` 40 | ```sql 41 | UPDATE interest_metrics 42 | SET month_year = TO_DATE(_year || '-' || LPAD(_month::text, 2, '0') || '-01', 'YYYY-MM-DD'); 43 | ``` 44 | ```sql 45 | SELECT* 46 | FROM interest_metrics 47 | ``` 48 |
      Answer:
      49 | Coding 50 | 59 | 60 | 61 |
    3. What is count of records in the fresh_segments.interest_metrics for each month_year value sorted in chronological order (earliest to latest) with the null values appearing first?
    4. 62 | 63 | ```sql 64 | SELECT 65 | month_year, 66 | COUNT(*) AS record_count 67 | FROM interest_metrics 68 | GROUP BY month_year 69 | ORDER BY month_year NULLS FIRST; 70 | 71 | ``` 72 | 73 |
      Answer:
      74 | Coding 75 | 89 | 90 | 91 |
    5. What do you think we should do with these null values in the fresh_segments.interest_metrics
    6. 92 | 93 | ```sql 94 | SELECT month_year, COUNT(*) AS record_count 95 | FROM interest_metrics 96 | WHERE month_year IS NOT NULL 97 | GROUP BY month_year 98 | ORDER BY month_year; 99 | ``` 100 |
      Answer:
      101 | Coding 102 | 118 | 119 | 120 |
    7. How many interest_id values exist in the fresh_segments.interest_metrics table but not in the fresh_segments.interest_map table? What about the other way around?
    8. 121 | 122 | ```sql 123 | SELECT COUNT(DISTINCT im.interest_id) AS count_interest_metrics_not_in_map 124 | FROM interest_metrics im 125 | LEFT JOIN interest_map map ON im.interest_id::integer = map.id 126 | WHERE map.id IS NULL; 127 | 128 | ``` 129 |
      Answer:
      130 | Coding 131 | 144 | 145 | 146 | ```sql 147 | SELECT COUNT(DISTINCT map.id) AS count_interest_map_not_in_metrics 148 | FROM interest_map map 149 | LEFT JOIN interest_metrics im ON map.id = im.interest_id::integer 150 | WHERE im.interest_id IS NULL; 151 | ``` 152 | 153 |
      Answer:
      154 | Coding 155 | 168 | 169 | 170 |
    9. Summarise the id values in the fresh_segments.interest_map by its total record count in this table
    10. 171 | 172 | ```sql 173 | SELECT id,interest_name, COUNT(*) AS record_count 174 | FROM interest_map im 175 | join interest_metrics ime on im.id=ime.interest_id::integer 176 | GROUP BY id,interest_name 177 | ORDER BY record_count DESC; 178 | ``` 179 |
      Answer:
      180 | Coding 181 | 199 | 200 | 201 | 202 |
    11. What sort of table join should we perform for our analysis and why? Check your logic by checking the rows where interest_id = 21246 in your joined output and include all columns from fresh_segments.interest_metrics and all columns from fresh_segments.interest_map except from the id column.
    12. 203 | 204 | ```sql 205 | SELECT 206 | im.*, 207 | map.interest_name AS mapped_interest_name, 208 | map.interest_summary AS mapped_interest_summary, 209 | map.created_at AS mapped_created_at, 210 | map.last_modified AS mapped_last_modified 211 | FROM interest_metrics AS im 212 | LEFT JOIN interest_map AS map ON im.interest_id::VARCHAR = map.id::VARCHAR 213 | WHERE im.interest_id = '21246'; 214 | ``` 215 | 216 |
      Answer:
      217 | Coding 218 | 235 | 236 | 237 |
    13. Are there any records in your joined table where the month_year value is before the created_at value from the fresh_segments.interest_map table? Do you think these values are valid and why? 238 |
    14. 239 | 240 | ```sql 241 | SELECT 242 | im.*, 243 | im.month_year AS interest_metrics_month_year, 244 | map.created_at AS interest_map_created_at 245 | FROM 246 | interest_metrics AS im 247 | LEFT JOIN 248 | interest_map AS map 249 | ON 250 | im.interest_id = map.id::varchar 251 | WHERE 252 | im.month_year < map.created_at 253 | ORDER BY 254 | im.interest_id, im.month_year; 255 | ``` 256 |
      Answer:
      257 | Coding 258 | 275 |
    276 | 277 |

    B. Interest Analysis

    278 |
      279 |
    1. Which interests have been present in all month_year dates in our dataset?
    2. 280 | 281 | ```sql 282 | SELECT DISTINCT interest_id 283 | FROM interest_metrics 284 | GROUP BY interest_id 285 | HAVING COUNT(DISTINCT month_year) = (SELECT COUNT(DISTINCT month_year) FROM interest_metrics); 286 | ``` 287 |
      Answer:
      288 | Coding 289 | 300 | 301 | 302 |
    3. Using this same total_months measure - calculate the cumulative percentage of all records starting at 14 months - which total_months value passes the 90% cumulative percentage value?
    4. 303 | 304 | ```sql 305 | WITH MonthlyInterestCounts AS ( 306 | SELECT interest_id, COUNT(DISTINCT month_year) AS month_count 307 | FROM interest_metrics 308 | GROUP BY interest_id 309 | ), 310 | InterestCumulativePercentage AS ( 311 | SELECT 312 | month_count, 313 | COUNT(interest_id) AS interest_count, 314 | SUM(COUNT(interest_id)) OVER (ORDER BY month_count DESC) AS total_interest_count 315 | FROM MonthlyInterestCounts 316 | GROUP BY month_count 317 | ) 318 | SELECT 319 | month_count, 320 | total_interest_count, 321 | ROUND(total_interest_count * 100.0 / (SELECT SUM(interest_count) FROM InterestCumulativePercentage), 2) AS cumulative_percent 322 | FROM InterestCumulativePercentage 323 | WHERE ROUND(total_interest_count * 100.0 / (SELECT SUM(interest_count) FROM InterestCumulativePercentage), 2) > 90; 324 | ``` 325 |
      Answer:
      326 | Coding 327 | 342 | 343 | 344 |
    5. If we were to remove all interest_id values which are lower than the total_months value we found in the previous question - how many total data points would we be removing?
    6. 345 | 346 | ```sql 347 | WITH InterestMonthsCounts AS ( 348 | SELECT interest_id, COUNT(DISTINCT month_year) AS month_count 349 | FROM interest_metrics 350 | GROUP BY interest_id 351 | ), 352 | TotalMonths AS ( 353 | SELECT MAX(month_count) AS total_months 354 | FROM InterestMonthsCounts 355 | ) 356 | SELECT SUM(imc.month_count) AS total_data_points_to_keep, 357 | (SELECT COUNT(*) FROM interest_metrics) - SUM(imc.month_count) AS total_data_points_removed 358 | FROM InterestMonthsCounts imc 359 | JOIN TotalMonths tm ON imc.month_count >= tm.total_months; 360 | ``` 361 |
      Answer:
      362 | Coding 363 | 377 |
    378 | 379 |

    C. Segment Analysis

    380 |
      381 |
    1. Using our filtered dataset by removing the interests with less than 6 months worth of data, which are the top 10 and bottom 10 interests which have the largest composition values in any month_year? Only use the maximum composition value for each interest but you must keep the corresponding month_year
    2. 382 | 383 | ```sql 384 | WITH cte AS ( 385 | SELECT interest_id, COUNT(DISTINCT month_year) AS month_count 386 | FROM interest_metrics 387 | GROUP BY interest_id 388 | HAVING COUNT(DISTINCT month_year) >= 6 389 | ) 390 | 391 | SELECT * 392 | INTO filtered_table 393 | FROM interest_metrics 394 | WHERE interest_id IN (SELECT interest_id FROM cte); 395 | 396 | -- Top 10 interests with largest composition values 397 | SELECT 398 | f.month_year, 399 | f.interest_id, 400 | im.interest_name, 401 | MAX(f.composition) AS max_composition 402 | FROM filtered_table f 403 | JOIN interest_map im ON f.interest_id = im.id::varchar 404 | GROUP BY f.month_year, f.interest_id, im.interest_name 405 | ORDER BY max_composition DESC 406 | LIMIT 10; 407 | 408 | -- Bottom 10 interests with smallest composition values 409 | SELECT 410 | f.month_year, 411 | f.interest_id, 412 | im.interest_name, 413 | MAX(f.composition) AS max_composition 414 | FROM filtered_table f 415 | JOIN interest_map im ON f.interest_id = im.id::varchar 416 | GROUP BY f.month_year, f.interest_id, im.interest_name 417 | ORDER BY max_composition ASC 418 | LIMIT 10; 419 | ``` 420 |
      Answer:
      421 | Coding 422 | 430 | 431 | 438 | 439 | 450 | 451 | 462 | 463 | 464 |
    3. Which 5 interests had the lowest average ranking value?
    4. 465 | 466 | ```sql 467 | SELECT 468 | f.interest_id, 469 | im.interest_name, 470 | AVG(f.ranking) AS avg_ranking 471 | FROM filtered_table f 472 | JOIN interest_map im ON f.interest_id = im.id::varchar 473 | GROUP BY f.interest_id, im.interest_name 474 | ORDER BY avg_ranking ASC 475 | LIMIT 5; 476 | ``` 477 |
      Answer:
      478 | Coding 479 | 480 | 491 | 492 | 493 |
    5. Which 5 interests had the lowest average ranking value?
    6. 494 | 495 | ```sql 496 | SELECT 497 | f.interest_id, 498 | im.interest_name, 499 | STDDEV(f.percentile_ranking) AS std_dev_percentile_ranking 500 | FROM filtered_table f 501 | JOIN interest_map im ON f.interest_id = im.id::varchar 502 | GROUP BY f.interest_id, im.interest_name 503 | ORDER BY std_dev_percentile_ranking DESC 504 | LIMIT 5; 505 | ``` 506 |
      Answer:
      507 | Coding 508 | 519 |
    520 | 521 |

    D. Index Analysis

    522 |
      523 |
    1. What is the top 10 interests by the average composition for each month?
    2. 524 | 525 | ```sql 526 | SELECT 527 | _month, 528 | _year, 529 | month_year, 530 | interest_id, 531 | ROUND(SUM(composition)::numeric / SUM(index_value)::numeric, 2) AS average_composition 532 | FROM interest_metrics 533 | GROUP BY _month, _year, month_year, interest_id 534 | ORDER BY _year, _month, average_composition DESC 535 | LIMIT 10; 536 | ``` 537 |
      Answer:
      538 | Coding 539 | 548 | 549 | 550 |
    3. For all of these top 10 interests - which interest appears the most often?
    4. 551 | 552 | ```sql 553 | WITH ranks_tab AS ( 554 | SELECT 555 | i.interest_id, 556 | interest_name, 557 | month_year, 558 | AVG(composition / index_value) AS avg_composition, 559 | RANK() OVER (PARTITION BY month_year ORDER BY AVG(composition / index_value) DESC) AS ranks 560 | FROM interest_metrics i 561 | JOIN interest_map m ON i.interest_id = m.id::varchar 562 | GROUP BY i.interest_id, interest_name, month_year 563 | ) 564 | SELECT 565 | interest_id, 566 | interest_name, 567 | COUNT(*) OVER (PARTITION BY interest_name) AS counts 568 | FROM ranks_tab 569 | WHERE ranks <= 10 570 | ORDER BY 3 DESC; 571 | ``` 572 |
      Answer:
      573 | Coding 574 | 589 | 590 | 591 |
    5. What is the average of the average composition for the top 10 interests for each month?
    6. 592 | 593 | ```sql 594 | WITH ranks_tab AS ( 595 | SELECT 596 | i.interest_id, 597 | interest_name, 598 | month_year, 599 | AVG(composition / index_value) AS avg_composition, 600 | RANK() OVER (PARTITION BY month_year ORDER BY AVG(composition / index_value) DESC) AS ranks 601 | FROM interest_metrics i 602 | JOIN interest_map m ON i.interest_id = m.id::varchar 603 | GROUP BY i.interest_id, interest_name, month_year 604 | ) 605 | SELECT 606 | month_year, 607 | AVG(avg_composition) AS average_avg_composition 608 | FROM ranks_tab 609 | WHERE ranks <= 10 610 | GROUP BY month_year 611 | ORDER BY month_year; 612 | ``` 613 | 614 |
      Answer:
      615 | Coding 616 | 632 |
    633 | 634 | 635 | 636 | 637 | 638 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 8 Week SQL challenge🔍 2 |

    This repository serves as a comprehensive solution for the #8WeekSQLChallenge, encompassing eight distinct case studies.The repository is a testament to my prowess in SQL, as it demonstrates my adeptness in solving diverse SQL challenges and showcases my expertise in query composition and problem-solving. These case studies cover a wide array of topics, including ranking, common table expressions (CTEs), datetime functions, text manipulation, aggregation, NULL handling, and more.
    3 | 4 | This repository reflects the culmination of my journey through various SQL challenges. Each case study presents a unique problem-solving scenario that required me to apply a range of SQL techniques such as CTEs, case statements, date functions, and complex aggregations. As a result, I have honed my skills in SQL query crafting, data manipulation, and analysis.
    5 | 6 | Through this repository, I proudly present my ability to tackle intricate SQL challenges and exemplify my aptitude for effectively addressing real-world data scenarios. It serves as a testament to my growth, proficiency, and innovation in the realm of SQL.
    7 | The creator behind the development of the #8WeekSQLChallenge is Danny Maa.

    8 | 9 |

    Feel free to reach out for any questions or suggestions about this project. I'm open to discussions and eager to assist. 10 | 11 | Linkedln | Mariya Joseph
    12 | 13 | Don't forget to follow and star ⭐ the repository if you find it valuable.

    14 |

    Tools Used🛠️ : PostgreSQL

    15 | 16 |

    CONTENTS📝

    17 | 58 | --------------------------------------------------------------------------------