|
| 1 | +-- CASE STUDY: Danny’s Diner |
| 2 | +-- QUERYING DATA WITH SQL |
| 3 | +-- Mr Danny, a restaurant owner is interested in having information about his customers, |
| 4 | +-- especially about their visiting patterns, how much money they’ve spent and also, which menu items are their favorite. |
| 5 | +-- Having this deeper connection with his customers will help him deliver a better and more personalized experience for his loyal customers. |
| 6 | +-- He also needs these insights to help him decide whether he should expand the existing customer loyalty program or not. |
| 7 | +-- 3 key datasets were presented for analysis: |
| 8 | +-- sales |
| 9 | +-- menu |
| 10 | +-- members |
| 11 | + |
| 12 | +QUESTIONS |
| 13 | +--1. What is the total amount each customer spent at the restaurant? |
| 14 | +SELECT s.customer_id, SUM(m.price) as total_spent |
| 15 | +FROM dannys_diner.sales s |
| 16 | +LEFT JOIN dannys_diner.menu m |
| 17 | +ON s.product_id = m.product_id |
| 18 | +GROUP BY 1 |
| 19 | +ORDER BY 2 |
| 20 | + |
| 21 | +--2. How many days has each customer visited the restaurant? |
| 22 | +WITH sub1 AS |
| 23 | +(SELECT order_date,customer_id, COUNT(customer_id) as count |
| 24 | +FROM dannys_diner.sales |
| 25 | +GROUP BY 1,2 |
| 26 | +ORDER BY 1) |
| 27 | + |
| 28 | +SELECT customer_id, COUNT (sub1.order_date) |
| 29 | +FROM sub1 |
| 30 | +GROUP BY 1 |
| 31 | +ORDER BY 1 |
| 32 | + |
| 33 | +--3. What was the first item from the menu purchased by each customer? |
| 34 | +WITH sub1 AS ( |
| 35 | + SELECT s.customer_id, s.order_date, m.product_name, |
| 36 | + RANK() OVER(PARTITION BY customer_id ORDER BY order_date) as rank |
| 37 | + FROM dannys_diner.sales s |
| 38 | + LEFT JOIN dannys_diner.menu m |
| 39 | + ON s.product_id = m.product_id |
| 40 | + ORDER BY 2) |
| 41 | + |
| 42 | +SELECT DISTINCT customer_id, product_name, order_date |
| 43 | +FROM sub1 |
| 44 | +WHERE rank = 1 |
| 45 | + |
| 46 | +--4. What is the most purchased item on the menu and how many times was it purchased by all customers? |
| 47 | +SELECT m.product_name, |
| 48 | + COUNT(s.product_id) |
| 49 | +FROM dannys_diner.sales s |
| 50 | +JOIN dannys_diner.menu m |
| 51 | +USING (product_id) |
| 52 | +GROUP BY 1 |
| 53 | +ORDER BY 2 desc |
| 54 | +LIMIT 1 |
| 55 | + |
| 56 | + |
| 57 | + |
| 58 | +--5. Which item was the most popular for each customer? |
| 59 | +WITH sub1 AS ( |
| 60 | +SELECT s.customer_id, |
| 61 | + m.product_name, |
| 62 | + COUNT(m.product_name) times_ordered, |
| 63 | + RANK() OVER(PARTITION BY customer_id ORDER BY COUNT(m.product_name)DESC) AS rank |
| 64 | +FROM dannys_diner.sales s |
| 65 | +LEFT JOIN dannys_diner.menu m |
| 66 | +ON s.product_id = m.product_id |
| 67 | +GROUP BY 1, 2) |
| 68 | + |
| 69 | +SELECT customer_id, product_name, times_ordered |
| 70 | +FROM sub1 |
| 71 | +WHERE rank=1 |
| 72 | + |
| 73 | +--6. Which item was purchased first by the customer after they became a member? |
| 74 | +WITH sub1 as ( |
| 75 | + SELECT mb.customer_id, m.product_name, s.order_date, mb.join_date, |
| 76 | + RANK() OVER(PARTITION BY mb.customer_id ORDER BY s.order_date) AS rank |
| 77 | + FROM dannys_diner.sales s |
| 78 | + LEFT JOIN dannys_diner.menu m |
| 79 | + ON s.product_id = m.product_id |
| 80 | + LEFT JOIN dannys_diner.members mb |
| 81 | + ON s.customer_id = mb.customer_id |
| 82 | + WHERE s.order_date > mb.join_date) |
| 83 | + |
| 84 | +SELECT * |
| 85 | +FROM sub1 |
| 86 | +WHERE rank = 1 |
| 87 | + |
| 88 | +--7. Which item was purchased just before the customer became a member? |
| 89 | +WITH sub1 AS ( |
| 90 | + SELECT mb.customer_id, m.product_name, s.order_date, mb.join_date, |
| 91 | + RANK() OVER(PARTITION BY mb.customer_id ORDER BY s.order_date desc) AS rank |
| 92 | + FROM dannys_diner.sales s |
| 93 | + LEFT JOIN dannys_diner.menu m |
| 94 | + ON s.product_id = m.product_id |
| 95 | + LEFT JOIN dannys_diner.members mb |
| 96 | + ON s.customer_id = mb.customer_id |
| 97 | + WHERE s.order_date < mb.join_date |
| 98 | + ) |
| 99 | + |
| 100 | +SELECT * |
| 101 | +FROM sub1 |
| 102 | +WHERE rank = 1 |
| 103 | + |
| 104 | +--8. What is the total items and amount spent for each member before they became a member? |
| 105 | +SELECT DISTINCT s.customer_id, m.product_name, COUNT(s.product_id), SUM(m.price) as total_spent |
| 106 | +FROM dannys_diner.sales s |
| 107 | +LEFT JOIN dannys_diner.menu m |
| 108 | +ON s.product_id = m.product_id |
| 109 | +LEFT JOIN dannys_diner.members mb |
| 110 | +ON s.customer_id = mb.customer_id |
| 111 | +GROUP BY 1,2, s.order_date, mb.join_date |
| 112 | +HAVING s.order_date < mb.join_date |
| 113 | +ORDER BY 1 |
| 114 | + |
| 115 | +--9. If each $1 spent equates to 10 points and sushi has a 2x points multiplier - how many points would each customer have? |
| 116 | +WITH sub1 AS ( |
| 117 | + SELECT s.customer_id, m.product_name, COUNT(s.product_id), SUM(m.price) as total_spent, |
| 118 | + CASE WHEN m.product_name= 'sushi' THEN 2 * 10 * SUM(m.price) |
| 119 | + ELSE 10 * SUM(m.price) end as points |
| 120 | + FROM dannys_diner.sales s |
| 121 | + LEFT JOIN dannys_diner.menu m |
| 122 | + ON s.product_id = m.product_id |
| 123 | + LEFT JOIN dannys_diner.members mb |
| 124 | + ON s.customer_id = mb.customer_id |
| 125 | + GROUP BY 1,2 |
| 126 | + ) |
| 127 | +SELECT customer_id, SUM(points) |
| 128 | +FROM sub1 |
| 129 | +GROUP BY 1 |
| 130 | +ORDER BY 1 |
| 131 | + |
| 132 | +--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? |
| 133 | +With sub1 AS ( |
| 134 | + SELECT s.customer_id, m.product_name,s.order_date, mb.join_date, |
| 135 | + COUNT(s.product_id), SUM(m.price) AS total_spent, |
| 136 | + CASE WHEN s.order_date BETWEEN mb.join_date - 1 AND mb.join_date + 7 |
| 137 | + OR m.product_name= 'sushi' THEN 2 * 10 * SUM(m.price) |
| 138 | + ELSE 10 * SUM(m.price) END AS points |
| 139 | + FROM dannys_diner.sales s |
| 140 | + LEFT JOIN dannys_diner.menu m |
| 141 | + ON s.product_id = m.product_id |
| 142 | + LEFT JOIN dannys_diner.members mb |
| 143 | + ON s.customer_id = mb.customer_id |
| 144 | + GROUP BY 1,2,3,4 |
| 145 | + ) |
| 146 | +SELECT customer_id, SUM(points) |
| 147 | +FROM sub1 |
| 148 | +GROUP BY 1 |
| 149 | +ORDER BY 1 |
| 150 | + |
| 151 | +-- INSIGHTS |
| 152 | +-- • Customer A has spent the most money in the restaurant, and this is closely followed by customer B with a difference of just $2. |
| 153 | +-- • Customer B however, has visited the store more than any other customer has. |
| 154 | +-- • Curry was most ordered item on the menu for first time customers. |
| 155 | +-- • Overall, Ramen was the most purchased item on the menu. |
| 156 | +-- • Data trends amongst the individual purchases showed ramen as the most frequent purchase amongst all customers as well. |
| 157 | +-- • Customers spent more money when the became members, compared to when they were not members of the loyalty program |
| 158 | +-- • The point-based reward system can drive purchase of a particular product on the menu if its points are more rewarding. |
| 159 | + |
| 160 | +-- RECOMMENDATIONS |
| 161 | +-- • The natural endearment towards ramen shows that it is a stellar product and this should be maximized. Ramen should be highlighted and prominently displayed on the menu with a compelling and mouth-watering description. |
| 162 | +-- • Special deals or promotions that focus on ramen, such as a discount for ordering it, more reward points, or a complimentary drink or dessert should be considered |
| 163 | +-- • More data that can encourage targeted serving of customers should be collected e.g. addresses, opinion on delivery services, customer feedback etc. |
| 164 | +-- • A positive experience in the restaurant will definitely increase sales and drive customer repeat purchases. This refers to how customers are treated by staff. |
| 165 | +-- • Members are observed to spend more money, so strategies must be put in place to convert customers to members |
| 166 | +-- • The point-based reward system works and should be encouraged. This system does not have to be fixed but can be flexible to ensure that different products can be promoted at different times. |
| 167 | + |
| 168 | + |
| 169 | +--These datasets were gotten from the Danny Ma’s 8 weeks SQL challenge. |
| 170 | +--The Schema SQL code for the creation of permanent tables used for this project is attached below |
| 171 | + |
| 172 | + |
| 173 | +CREATE SCHEMA dannys_diner; |
| 174 | +SET search_path = dannys_diner; |
| 175 | + |
| 176 | +CREATE TABLE sales ( |
| 177 | + "customer_id" VARCHAR(1), |
| 178 | + "order_date" DATE, |
| 179 | + "product_id" INTEGER |
| 180 | +); |
| 181 | + |
| 182 | +INSERT INTO sales |
| 183 | + ("customer_id", "order_date", "product_id") |
| 184 | +VALUES |
| 185 | + ('A', '2021-01-01', '1'), |
| 186 | + ('A', '2021-01-01', '2'), |
| 187 | + ('A', '2021-01-07', '2'), |
| 188 | + ('A', '2021-01-10', '3'), |
| 189 | + ('A', '2021-01-11', '3'), |
| 190 | + ('A', '2021-01-11', '3'), |
| 191 | + ('B', '2021-01-01', '2'), |
| 192 | + ('B', '2021-01-02', '2'), |
| 193 | + ('B', '2021-01-04', '1'), |
| 194 | + ('B', '2021-01-11', '1'), |
| 195 | + ('B', '2021-01-16', '3'), |
| 196 | + ('B', '2021-02-01', '3'), |
| 197 | + ('C', '2021-01-01', '3'), |
| 198 | + ('C', '2021-01-01', '3'), |
| 199 | + ('C', '2021-01-07', '3'); |
| 200 | + |
| 201 | + |
| 202 | +CREATE TABLE menu ( |
| 203 | + "product_id" INTEGER, |
| 204 | + "product_name" VARCHAR(5), |
| 205 | + "price" INTEGER |
| 206 | +); |
| 207 | + |
| 208 | +INSERT INTO menu |
| 209 | + ("product_id", "product_name", "price") |
| 210 | +VALUES |
| 211 | + ('1', 'sushi', '10'), |
| 212 | + ('2', 'curry', '15'), |
| 213 | + ('3', 'ramen', '12'); |
| 214 | + |
| 215 | + |
| 216 | +CREATE TABLE members ( |
| 217 | + "customer_id" VARCHAR(1), |
| 218 | + "join_date" DATE |
| 219 | +); |
| 220 | + |
| 221 | +INSERT INTO members |
| 222 | + ("customer_id", "join_date") |
| 223 | +VALUES |
| 224 | + ('A', '2021-01-07'), |
| 225 | + ('B', '2021-01-09'); |
0 commit comments