Welcome to Subscribe On Youtube

3705. Find Golden Hour Customers

Description

Table: restaurant_orders

++-+
\| order_id         \| int      \|
\| customer_id      \| int      \|
\| order_timestamp  \| datetime \|
\| order_amount     \| decimal  \|
\| payment_method   \| varchar  \|
\| order_rating     \| int      \|
++-+-+-+--+
\| order_id \| customer_id \| order_timestamp     \| order_amount \| payment_method \| order_rating \|
++--+-+-+-+--+

Output:

+-+--+-+
\| customer_id \| total_orders \| peak_hour_percentage \| average_rating \|
+-+--+-+
\| 103         \| 3            \| 100                  \| 4.67           \|
\| 101         \| 4            \| 100                  \| 4.67           \|
\| 105         \| 3            \| 100                  \| 4.33           \|
+-+--+-+

Explanation:

  • Customer 101:
    • Total orders: 4 (at least 3) 
    • Peak hour orders: 4 out of 4 (12:30, 19:15, 13:45, and 20:30 are in peak hours)
    • Peak hour percentage: 100% (at least 60%) 
    • Rated orders: 3 out of 4 (75% rating completion) 
    • Average rating: (5+4+5)/3 = 4.67 (at least 4.0) 
    • Result: Golden hour customer
  • Customer 102:
    • Total orders: 3 (at least 3) 
    • Peak hour orders: 2 out of 3 (11:30, 12:00 are in peak hours; 15:30 is not)
    • Peak hour percentage: 2/3 = 66.67% (at least 60%) 
    • Rated orders: 2 out of 3 (66.67% rating completion) 
    • Average rating: (4+3)/2 = 3.5 (less than 4.0) 
    • Result: Not a golden hour customer (average rating too low)
  • Customer 103:
    • Total orders: 3 (at least 3) 
    • Peak hour orders: 3 out of 3 (19:00, 20:45, 18:30 all in evening peak)
    • Peak hour percentage: 3/3 = 100% (at least 60%) 
    • Rated orders: 3 out of 3 (100% rating completion) 
    • Average rating: (5+4+5)/3 = 4.67 (at least 4.0) 
    • Result: Golden hour customer
  • Customer 104:
    • Total orders: 3 (at least 3) 
    • Peak hour orders: 0 out of 3 (10:00, 09:30, 16:00 all outside peak hours)
    • Peak hour percentage: 0/3 = 0% (less than 60%) 
    • Result: Not a golden hour customer (insufficient peak hour orders)
  • Customer 105:
    • Total orders: 3 (at least 3) 
    • Peak hour orders: 3 out of 3 (12:15, 13:00, 11:45 all in lunch peak)
    • Peak hour percentage: 3/3 = 100% (at least 60%) 
    • Rated orders: 3 out of 3 (100% rating completion) 
    • Average rating: (4+5+4)/3 = 4.33 (at least 4.0) 
    • Result: Golden hour customer

The results table is ordered by average_rating DESC, then customer_id DESC.

</div>

Solutions

Solution 1: Grouping and Statistics

We can group the orders by customer_id and calculate the total number of orders, number of orders during peak hours, number of rated orders, and average rating for each customer. Then we filter based on the conditions in the problem and sort by average rating in descending order, followed by customer ID in descending order.

  • import pandas as pd
    import numpy as np
    
    
    def find_golden_hour_customers(restaurant_orders: pd.DataFrame) -> pd.DataFrame:
        df = restaurant_orders.copy()
        df["order_timestamp"] = pd.to_datetime(df["order_timestamp"])
        df["is_peak_hour"] = df["order_timestamp"].dt.time.between(
            pd.to_datetime("11:00:00").time(), pd.to_datetime("14:00:00").time()
        ) | df["order_timestamp"].dt.time.between(
            pd.to_datetime("18:00:00").time(), pd.to_datetime("21:00:00").time()
        )
        grouped = (
            df.groupby("customer_id")
            .agg(
                total_orders=("order_timestamp", "count"),
                peak_hour_count=("is_peak_hour", "sum"),
                average_rating=("order_rating", lambda x: x.dropna().mean()),
                non_null_rating_count=("order_rating", lambda x: x.notna().sum()),
            )
            .reset_index()
        )
        grouped["average_rating"] = grouped["average_rating"].round(2)
        grouped["peak_hour_percentage"] = (
            grouped["peak_hour_count"] / grouped["total_orders"] * 100
        ).round()
        filtered = grouped[
            (grouped["total_orders"] >= 3)
            & (grouped["peak_hour_percentage"] >= 60)
            & (grouped["average_rating"] >= 4.0)
            & (grouped["non_null_rating_count"] / grouped["total_orders"] >= 0.5)
        ]
        filtered = filtered.sort_values(
            by=["average_rating", "customer_id"], ascending=[False, False]
        )
        return filtered[
            ["customer_id", "total_orders", "peak_hour_percentage", "average_rating"]
        ]
    
    
  • # Write your MySQL query statement below
    SELECT
        customer_id,
        COUNT(1) total_orders,
        ROUND(
            SUM(
                TIME(order_timestamp) BETWEEN '11:00:00' AND '14:00:00'
                OR TIME(order_timestamp) BETWEEN '18:00:00' AND '21:00:00'
            ) / COUNT(1) * 100
        ) peak_hour_percentage,
        ROUND(AVG(order_rating), 2) average_rating
    FROM restaurant_orders
    GROUP BY customer_id
    HAVING
        total_orders >= 3
        AND peak_hour_percentage >= 60
        AND average_rating >= 4.0
        AND SUM(order_rating IS NOT NULL) / total_orders >= 0.5
    ORDER BY average_rating DESC, customer_id DESC;
    
    

All Problems

All Solutions