Find Hosts Meeting Listing, Rating, and Review-Coverage Rules
AirbnbData Engineer · OnsiteLast updated
Tests the ability to write a SQL query performing multi-table aggregations, date-windowed conditional logic, and host-level qualification filtering across listing counts, average ratings, and recent review coverage.
Problem Statement
Airbnb operations wants to identify high-performing, engaged "Superhosts" who maintain active inventory and consistently receive positive guest feedback.
Write a SQL query to find all hosts who meet all of the following criteria:
- The host owns at least 2 active listings (
is_active = TRUE). - The host's overall average rating across all reviews of their listings is at least 4.50.
- 100% of their active listings have received at least one review in the past 180 days relative to
'2024-01-01'(i.e.,review_datebetween'2023-07-05'and'2024-01-01', inclusive).
Schema
listings
| Column Name | Type | Description |
|---|---|---|
listing_id | INT | Primary key |
host_id | INT | ID of the host |
is_active | BOOLEAN | Whether the listing is currently active |
reviews
| Column Name | Type | Description |
|---|---|---|
review_id | INT | Primary key |
listing_id | INT | Foreign key referencing listings.listing_id |
rating | NUMERIC | Guest rating from 1.0 to 5.0 |
review_date | DATE | Date the review was submitted |
Output Format
Return the following columns, ordered by avg_rating descending, then host_id ascending:
host_id(INT)active_listing_count(INT): Total number of active listings for the host.avg_rating(NUMERIC): Overall average rating across all reviews for the host's listings, rounded to 2 decimal places.
Example
listings
+------------+---------+-----------+
| listing_id | host_id | is_active |
+------------+---------+-----------+
| 101 | 1 | TRUE |
| 102 | 1 | TRUE |
| 103 | 2 | TRUE |
| 104 | 2 | TRUE |
| 105 | 3 | TRUE |
+------------+---------+-----------+
reviews
+-----------+------------+--------+-------------+
| review_id | listing_id | rating | review_date |
+-----------+------------+--------+-------------+
| 1 | 101 | 4.8 | 2023-11-10 |
| 2 | 102 | 4.6 | 2023-12-01 |
| 3 | 103 | 4.9 | 2023-08-15 |
| 4 | 104 | 4.7 | 2022-01-10 |
| 5 | 105 | 5.0 | 2023-10-05 |
+-----------+------------+--------+-------------+
Output
+---------+----------------------+------------+
| host_id | active_listing_count | avg_rating |
+---------+----------------------+------------+
| 1 | 2 | 4.70 |
+---------+----------------------+------------+
Explanation:
- Host 1 has 2 active listings, an average rating of
(4.8 + 4.6) / 2 = 4.70 >= 4.50, and both listings have reviews after'2023-07-05'(100% coverage). Host 1 qualifies. - Host 2 has 2 active listings and an average rating of
4.80 >= 4.50, but listing 104 has no review within the 180-day window (only 50% coverage). Host 2 is excluded. - Host 3 only has 1 active listing (< 2). Host 3 is excluded.
Edge Cases to Consider
- Active listings with zero reviews ever should not satisfy the recent-review condition.
- A listing may have multiple reviews in the recent window; ensure distinct listing counts are used so duplicates do not inflate the coverage ratio.
- Inactive listings belonging to the host should not count towards active listing totals or coverage requirements.
Hints
Hint 1
Start by aggregating reviews at the listing level first or computing whether each active listing has at least one review within the 180-day window.
Hint 2
Join active listings to your listing-level review indicators so that listings with zero reviews are retained as having zero recent reviews.
Hint 3
Group by host and compare `COUNT(DISTINCT listing_id)` against the count of distinct listings that have a recent review within a `HAVING` clause.
Follow-up questions
- How would you rewrite the query if the coverage threshold changed from 100% to a configurable parameter like 80%?
- If the dataset contains 500 million reviews and 50 million listings, how would you optimize query execution and indexing?
- How would you modify this query if the 180-day window must be evaluated dynamically relative to `CURRENT_DATE` instead of a static date?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.