Skip to content

Commit 36336b2

Browse files
authored
Added task 3705
1 parent 5366d48 commit 36336b2

File tree

3 files changed

+225
-0
lines changed

3 files changed

+225
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
3705\. Find Golden Hour Customers
2+
3+
Medium
4+
5+
Table: `restaurant_orders`
6+
7+
+------------------+----------+
8+
| Column Name | Type |
9+
+------------------+----------+
10+
| order_id | int |
11+
| customer_id | int |
12+
| order_timestamp | datetime |
13+
| order_amount | decimal |
14+
| payment_method | varchar |
15+
| order_rating | int |
16+
+------------------+----------+
17+
order_id is the unique identifier for this table.
18+
payment_method can be cash, card, or app.
19+
order_rating is between 1 and 5, where 5 is the best (NULL if not rated).
20+
order_timestamp contains both date and time information.
21+
22+
Write a solution to find **golden hour customers** - customers who consistently order during peak hours and provide high satisfaction. A customer is a **golden hour customer** if they meet ALL the following criteria:
23+
24+
* Made **at least** `3` orders.
25+
* **At least** `60%` of their orders are during **peak hours **(`11:00`\-`14:00` or `18:00`\-`21:00`).
26+
* Their **average rating** for rated orders is at least `4.0,` round it to `2` decimal places.
27+
* Have rated **at least** `50%` of their orders.
28+
29+
Return _the result table ordered by_ `average_rating` _in **descending** order, then by_ `customer_id` _in **descending** order_.
30+
31+
The result format is in the following example.
32+
33+
**Example:**
34+
35+
**Input:**
36+
37+
restaurant\_orders table:
38+
39+
+----------+-------------+---------------------+--------------+----------------+--------------+
40+
| order_id | customer_id | order_timestamp | order_amount | payment_method | order_rating |
41+
+----------+-------------+---------------------+--------------+----------------+--------------+
42+
| 1 | 101 | 2024-03-01 12:30:00 | 25.50 | card | 5 |
43+
| 2 | 101 | 2024-03-02 19:15:00 | 32.00 | app | 4 |
44+
| 3 | 101 | 2024-03-03 13:45:00 | 28.75 | card | 5 |
45+
| 4 | 101 | 2024-03-04 20:30:00 | 41.00 | app | NULL |
46+
| 5 | 102 | 2024-03-01 11:30:00 | 18.50 | cash | 4 |
47+
| 6 | 102 | 2024-03-02 12:00:00 | 22.00 | card | 3 |
48+
| 7 | 102 | 2024-03-03 15:30:00 | 19.75 | cash | NULL |
49+
| 8 | 103 | 2024-03-01 19:00:00 | 55.00 | app | 5 |
50+
| 9 | 103 | 2024-03-02 20:45:00 | 48.50 | app | 4 |
51+
| 10 | 103 | 2024-03-03 18:30:00 | 62.00 | card | 5 |
52+
| 11 | 104 | 2024-03-01 10:00:00 | 15.00 | cash | 3 |
53+
| 12 | 104 | 2024-03-02 09:30:00 | 18.00 | cash | 2 |
54+
| 13 | 104 | 2024-03-03 16:00:00 | 20.00 | card | 3 |
55+
| 14 | 105 | 2024-03-01 12:15:00 | 30.00 | app | 4 |
56+
| 15 | 105 | 2024-03-02 13:00:00 | 35.50 | app | 5 |
57+
| 16 | 105 | 2024-03-03 11:45:00 | 28.00 | card | 4 |
58+
+----------+-------------+---------------------+--------------+----------------+--------------+
59+
60+
**Output:**
61+
62+
+-------------+--------------+----------------------+----------------+
63+
| customer_id | total_orders | peak_hour_percentage | average_rating |
64+
+-------------+--------------+----------------------+----------------+
65+
| 103 | 3 | 100 | 4.67 |
66+
| 101 | 4 | 75 | 4.67 |
67+
| 105 | 3 | 100 | 4.33 |
68+
+-------------+--------------+----------------------+----------------+
69+
70+
**Explanation:**
71+
72+
* **Customer 101**:
73+
* Total orders: 4 (at least 3)
74+
* Peak hour orders: 3 out of 4 (12:30, 19:15, 13:45, and 20:30 are in peak hours)
75+
* Peak hour percentage: 3/4 = 75% (at least 60%)
76+
* Rated orders: 3 out of 4 (75% rating completion)
77+
* Average rating: (5+4+5)/3 = 4.67 (at least 4.0)
78+
* Result: **Golden hour customer**
79+
* **Customer 102**:
80+
* Total orders: 3 (at least 3)
81+
* Peak hour orders: 2 out of 3 (11:30, 12:00 are in peak hours; 15:30 is not)
82+
* Peak hour percentage: 2/3 = 66.67% (at least 60%)
83+
* Rated orders: 2 out of 3 (66.67% rating completion)
84+
* Average rating: (4+3)/2 = 3.5 (less than 4.0)
85+
* Result: **Not a golden hour customer** (average rating too low)
86+
* **Customer 103**:
87+
* Total orders: 3 (at least 3)
88+
* Peak hour orders: 3 out of 3 (19:00, 20:45, 18:30 all in evening peak)
89+
* Peak hour percentage: 3/3 = 100% (at least 60%)
90+
* Rated orders: 3 out of 3 (100% rating completion)
91+
* Average rating: (5+4+5)/3 = 4.67 (at least 4.0)
92+
* Result: **Golden hour customer**
93+
* **Customer 104**:
94+
* Total orders: 3 (at least 3)
95+
* Peak hour orders: 0 out of 3 (10:00, 09:30, 16:00 all outside peak hours)
96+
* Peak hour percentage: 0/3 = 0% (less than 60%)
97+
* Result: **Not a golden hour customer** (insufficient peak hour orders)
98+
* **Customer 105**:
99+
* Total orders: 3 (at least 3)
100+
* Peak hour orders: 3 out of 3 (12:15, 13:00, 11:45 all in lunch peak)
101+
* Peak hour percentage: 3/3 = 100% (at least 60%)
102+
* Rated orders: 3 out of 3 (100% rating completion)
103+
* Average rating: (4+5+4)/3 = 4.33 (at least 4.0)
104+
* Result: **Golden hour customer**
105+
106+
The results table is ordered by average\_rating DESC, then customer\_id DESC.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Write your MySQL query statement below
2+
# #Medium #Database #2025_10_10_Time_281_ms_(71.26%)_Space_0.0_MB_(100.00%)
3+
SELECT
4+
customer_id,
5+
COUNT(order_id) AS total_orders,
6+
ROUND(
7+
(
8+
SUM(
9+
CASE
10+
WHEN HOUR(order_timestamp) BETWEEN 11 AND 13
11+
OR HOUR(order_timestamp) BETWEEN 18 AND 20
12+
THEN 1 ELSE 0
13+
END
14+
) * 100.0
15+
) / COUNT(order_id)
16+
) AS peak_hour_percentage,
17+
ROUND(AVG(order_rating), 2) AS average_rating
18+
FROM restaurant_orders
19+
GROUP BY customer_id
20+
HAVING
21+
(SUM(CASE WHEN order_rating IS NOT NULL THEN 1 ELSE 0 END) * 1.0 / COUNT(order_id)) >= 0.5
22+
AND COUNT(order_id) >= 3
23+
AND (
24+
(
25+
SUM(
26+
CASE
27+
WHEN HOUR(order_timestamp) BETWEEN 11 AND 13
28+
OR HOUR(order_timestamp) BETWEEN 18 AND 20
29+
THEN 1 ELSE 0
30+
END
31+
) * 100.0
32+
) / COUNT(order_id)
33+
) >= 60
34+
AND AVG(order_rating) >= 4.0
35+
ORDER BY AVG(order_rating) DESC, customer_id DESC;
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
package g3701_3800.s3705_find_golden_hour_customers;
2+
3+
import static org.hamcrest.CoreMatchers.equalTo;
4+
import static org.hamcrest.MatcherAssert.assertThat;
5+
6+
import java.io.BufferedReader;
7+
import java.io.FileNotFoundException;
8+
import java.io.FileReader;
9+
import java.sql.Connection;
10+
import java.sql.ResultSet;
11+
import java.sql.SQLException;
12+
import java.sql.Statement;
13+
import java.util.stream.Collectors;
14+
import javax.sql.DataSource;
15+
import org.junit.jupiter.api.Test;
16+
import org.zapodot.junit.db.annotations.EmbeddedDatabase;
17+
import org.zapodot.junit.db.annotations.EmbeddedDatabaseTest;
18+
import org.zapodot.junit.db.common.CompatibilityMode;
19+
20+
@EmbeddedDatabaseTest(
21+
compatibilityMode = CompatibilityMode.MySQL,
22+
initialSqls =
23+
"CREATE TABLE restaurant_orders ("
24+
+ " order_id INTEGER,"
25+
+ " customer_id INTEGER NOT NULL,"
26+
+ " order_timestamp DATETIME NOT NULL,"
27+
+ " order_amount DECIMAL(10,2) NOT NULL,"
28+
+ " payment_method VARCHAR(20) NOT NULL,"
29+
+ " order_rating INTEGER"
30+
+ ");"
31+
+ "INSERT INTO restaurant_orders (order_id, customer_id, "
32+
+ "order_timestamp, order_amount, payment_method, order_rating) VALUES"
33+
+ "(1, 101, '2024-03-01 12:30:00', 25.50, 'card', 5),"
34+
+ "(2, 101, '2024-03-02 19:15:00', 32.00, 'app', 4),"
35+
+ "(3, 101, '2024-03-03 13:45:00', 28.75, 'card', 5),"
36+
+ "(4, 101, '2024-03-04 20:30:00', 41.00, 'app', NULL),"
37+
+ "(5, 102, '2024-03-01 11:30:00', 18.50, 'cash', 4),"
38+
+ "(6, 102, '2024-03-02 12:00:00', 22.00, 'card', 3),"
39+
+ "(7, 102, '2024-03-03 15:30:00', 19.75, 'cash', NULL),"
40+
+ "(8, 103, '2024-03-01 19:00:00', 55.00, 'app', 5),"
41+
+ "(9, 103, '2024-03-02 20:45:00', 48.50, 'app', 4),"
42+
+ "(10, 103, '2024-03-03 18:30:00', 62.00, 'card', 5),"
43+
+ "(11, 104, '2024-03-01 10:00:00', 15.00, 'cash', 3),"
44+
+ "(12, 104, '2024-03-02 09:30:00', 18.00, 'cash', 2),"
45+
+ "(13, 104, '2024-03-03 16:00:00', 20.00, 'card', 3),"
46+
+ "(14, 105, '2024-03-01 12:15:00', 30.00, 'app', 4),"
47+
+ "(15, 105, '2024-03-02 13:00:00', 35.50, 'app', 5),"
48+
+ "(16, 105, '2024-03-03 11:45:00', 28.00, 'card', 4);")
49+
class MysqlTest {
50+
@Test
51+
void testScript(@EmbeddedDatabase DataSource dataSource)
52+
throws SQLException, FileNotFoundException {
53+
try (final Connection connection = dataSource.getConnection()) {
54+
try (final Statement statement = connection.createStatement();
55+
final ResultSet resultSet =
56+
statement.executeQuery(
57+
new BufferedReader(
58+
new FileReader(
59+
"src/main/java/g3701_3800/"
60+
+ "s3705_find_golden_hour_customers/"
61+
+ "script.sql"))
62+
.lines()
63+
.collect(Collectors.joining("\n"))
64+
.replaceAll("#.*?\\r?\\n", ""))) {
65+
assertThat(resultSet.next(), equalTo(true));
66+
assertThat(resultSet.getString(1), equalTo("103"));
67+
assertThat(resultSet.getString(2), equalTo("3"));
68+
assertThat(resultSet.getString(3), equalTo("100"));
69+
assertThat(resultSet.getString(4), equalTo("4.67"));
70+
assertThat(resultSet.next(), equalTo(true));
71+
assertThat(resultSet.getString(1), equalTo("101"));
72+
assertThat(resultSet.getString(2), equalTo("4"));
73+
assertThat(resultSet.getString(3), equalTo("100"));
74+
assertThat(resultSet.getString(4), equalTo("4.67"));
75+
assertThat(resultSet.next(), equalTo(true));
76+
assertThat(resultSet.getString(1), equalTo("105"));
77+
assertThat(resultSet.getString(2), equalTo("3"));
78+
assertThat(resultSet.getString(3), equalTo("100"));
79+
assertThat(resultSet.getString(4), equalTo("4.33"));
80+
assertThat(resultSet.next(), equalTo(false));
81+
}
82+
}
83+
}
84+
}

0 commit comments

Comments
 (0)