Riyadh Sale Listing Price Delta by District × Category
Date: 2026-09-23
Period: Q1 2025 to Q3 2026, calendar quarters (Q3 2026 is partial: Jul 1 – Sep 22)
Scope: Riyadh (city_id = 21), sale categories
Data Sources: sadb_listings, sadb_categories, sadb_districts
Question: How did the asking price of new sale listings in Riyadh change quarter by quarter since Q1 2025, when each (district_id, category) cluster is compared only with itself?
Companion report: Riyadh Rent Listing Price Delta.
Executive Summary
Section titled “Executive Summary”- Riyadh sale asking prices fell 9.4% from Q1 2025 to Q3 2026 (volume-weighted average delta), or −11.9% on the weighted geometric median, across 188 clusters and 139,741 listings. Only 23% of clusters ended higher than they started.
- Prices fell in all six quarters. The sharpest drop was Q4 2025 (−5.1% QoQ). The decline has slowed since then (−0.3% to −1.3% per quarter) but has not reversed. YoY Q3 2026 vs Q3 2025: −7.3%.
- Big Flat for Sale fell the most: −13.3%, with 94% of clusters down. It dropped −4.4% in Q2 2026, a second leg down after Q4 2025. An Narjis, Al Arid, Tuwaiq and Al Janadriyah are each down about 20%.
- Apartment for Sale: −9.4%. Prices fell in every quarter from Q3 2025 on, and the largest districts are down 7–13%.
- Villa for Sale: −6.9%. Almost all of the drop came in 2025 (Q2 −3.8% and Q4 −4.3%). Villa prices have held steady for three quarters, and Q3 2026 is the first small uptick (+0.7%).
- Land for Sale: −11.1% average and −26.6% per m². The drop was concentrated in Q4 2025 (−12.2% QoQ). Banban (−36%), Uraidh (−25%) and Al Arid (−24%) fell the most.
Methodology
Section titled “Methodology”| Choice | Value |
|---|---|
| Listings | city_id = 21, rega_licensed = 1, daily_rentable = 0, price > 0, not deleted |
| Quarter | Calendar quarter of create_time (Asia/Riyadh). Q3 2026 covers Jul 1 – Sep 22. |
| Outliers | Per cluster, prices outside the full-period p2–p98 range are dropped |
| Cluster panel | Balanced: only clusters with ≥ 10 listings in every one of the 7 quarters (188 sale clusters covering over 80% of Riyadh sale listings) |
| Weight | Cluster’s total listings over the period |
A balanced panel means every quarter is measured on exactly the same clusters. A district dropping in or out of a quarter can’t show up as a price change.
Estimators for the Q1 2025 → Q3 2026 delta:
- A: weighted mean of average-price deltas. Σ wᵢ·(avg_Q3’26ᵢ/avg_Q1’25ᵢ − 1) / Σ wᵢ. This is the headline “weighted average price delta”.
- C: weighted geometric mean of median ratios. exp(Σ wᵢ·ln(med_Q3’26ᵢ/med_Q1’25ᵢ) / Σ wᵢ) − 1. This is symmetric for rises and falls and resistant to a few extreme clusters.
- D: same as C on
meter_price(only meaningful for Land).
The quarterly index is Σ wᵢ·(pᵢ,q/refᵢ) / Σ wᵢ × 100, where refᵢ is the cluster’s full-period average. QoQ is index_q / index_q−1 − 1. Land uses the weighted geometric mean.
Weighted Price Delta by Category
Section titled “Weighted Price Delta by Category”Q1 2025 → Q3 2026, with a same-quarter YoY check (Q3 2026 vs Q3 2025, estimator A). Categories with ≥ 5 panel clusters are shown; the “All sale” row includes every category.
| Category | Clusters | Listings | Weighted avg price (Q1’25 → Q3’26) | A: wavg mean Δ | C: wgeo median Δ | D: wgeo /m² Δ | YoY Q3 Δ | % clusters up |
|---|---|---|---|---|---|---|---|---|
| All sale | 188 | 139,741 | −9.4% | −11.9% | −7.3% | 23% | ||
| Villa for Sale | 67 | 55,504 | 3,388,638 → 2,680,075 | −6.9% | −8.7% | −4.5% | 22% | |
| Apartment for Sale | 38 | 30,887 | 974,331 → 884,603 | −9.4% | −10.2% | −8.1% | 18% | |
| Big Flat for Sale | 31 | 28,109 | 1,117,543 → 961,648 | −13.3% | −13.7% | −10.8% | 6% | |
| Land for Sale | 41 | 23,232 | 3,412,147 → 2,923,568 | −11.1% | −18.7% | −26.6% | −9.5% | 34% |
| Building for Sale | 8 | 1,467 | 4,491,109 → 4,474,039 | +7.2% | −2.7% | +13.0% | 62% |
Building for Sale has only 8 clusters, and its estimators disagree on sign. Lounge for Sale (3 clusters) is left out of the table.
SQL Query
Section titled “SQL Query”WITH base AS ( SELECT l.district_id, l.category, toStartOfQuarter(toDateTime(l.create_time, 'Asia/Riyadh')) q, toFloat64(l.price) price, toFloat64(l.meter_price) mp FROM sadb_listings l FINAL WHERE l._peerdb_is_deleted = 0 AND l.rega_licensed = 1 AND l.daily_rentable = 0 AND l.price > 0 AND l.rent_period NOT IN (1, 2) AND l.district_id > 0 AND l.city_id = 21 AND l.create_time >= toUnixTimestamp(toDateTime('2025-01-01 00:00:00', 'Asia/Riyadh')) AND l.create_time < toUnixTimestamp(toDateTime('2026-09-23 00:00:00', 'Asia/Riyadh')) ), bounds AS ( SELECT district_id, category, quantile(0.02) (price) lo, quantile(0.98) (price) hi FROM base GROUP BY 1, 2 ), trimmed AS ( SELECT b.* FROM base b JOIN bounds x USING (district_id, category) WHERE b.price BETWEEN x.lo AND x.hi ), cq AS ( SELECT district_id, category, q, count() n FROM trimmed GROUP BY 1, 2, 3 ), -- balanced panel: >= 10 listings in all 7 quarters panel AS ( SELECT district_id, category, sum(n) w FROM cq GROUP BY 1, 2 HAVING count() = 7 AND min(n) >= 10 ), cl AS ( SELECT t.district_id district_id, t.category category, any(panel.w) w, avgIf (price, q = '2025-01-01') a0, avgIf (price, q = '2026-07-01') a1, avgIf (price, q = '2025-07-01') y0, medianIf (price, q = '2025-01-01') m0, medianIf (price, q = '2026-07-01') m1, medianIf ( mp, q = '2025-01-01' AND mp > 0 ) s0, medianIf ( mp, q = '2026-07-01' AND mp > 0 ) s1 FROM trimmed t JOIN panel USING (district_id, category) GROUP BY 1, 2 )SELECT c.name_en category, count() clusters, sum(w) listings, round(sum(w * a0) / sum(w)) wavg_q1_25, round(sum(w * a1) / sum(w)) wavg_q3_26, round(100 * sum(w * (a1 / a0 - 1)) / sum(w), 1) A_delta, round( 100 * (exp(sum(w * log(m1 / m0)) / sum(w)) - 1), 1 ) C_delta, round( 100 * ( exp( sumIf ( w * log(s1 / s0), s0 > 0 AND s1 > 0 ) / sumIf ( w, s0 > 0 AND s1 > 0 ) ) - 1 ), 1 ) D_sqm_delta, round(100 * sum(w * (a1 / y0 - 1)) / sum(w), 1) A_yoy_q3, round(100 * countIf (a1 > a0) / count()) pct_upFROM cl JOIN sadb_categories c FINAL ON cl.category = c.category_idWHERE positionCaseInsensitive(c.name_en, 'rent') = 0 -- sale categoriesGROUP BY ROLLUP (c.name_en)ORDER BY listings DESCQuarter-over-Quarter Delta
Section titled “Quarter-over-Quarter Delta”Each value is the weighted price change from the previous quarter (e.g. Q1’26 = Q1 2026 vs Q4 2025). Cumulative is Q3 2026 vs Q1 2025 on the index. It is slightly larger than estimator A above because the index averages normalized prices before dividing, while A averages each cluster’s ratio.
| Category | Q2’25 | Q3’25 | Q4’25 | Q1’26 | Q2’26 | Q3’26* | Cumulative | YoY Q3 |
|---|---|---|---|---|---|---|---|---|
| All sale | −1.3% | −2.3% | −5.1% | −1.3% | −0.3% | −1.3% | −11.2% | −7.9% |
| Villa for Sale | −3.8% | −1.2% | −4.3% | −0.7% | −0.6% | +0.7% | −9.5% | −4.9% |
| Apartment for Sale | +1.7% | −3.3% | −3.1% | −3.3% | −0.5% | −1.7% | −9.8% | −8.4% |
| Big Flat for Sale | +0.3% | −3.2% | −4.3% | −0.1% | −4.4% | −2.6% | −13.5% | −10.9% |
| Land for Sale | −0.2% | −2.0% | −12.2% | −1.1% | +4.9% | −4.1% | −14.4% | −12.5% |
* Q3 2026 is partial (Jul 1 – Sep 22).
Quarterly index (100 = each cluster’s own full-period average):
| Category | Q1’25 | Q2’25 | Q3’25 | Q4’25 | Q1’26 | Q2’26 | Q3’26* |
|---|---|---|---|---|---|---|---|
| All sale | 107.1 | 105.7 | 103.3 | 98.0 | 96.7 | 96.4 | 95.1 |
| Villa for Sale | 108.1 | 104.0 | 102.8 | 98.4 | 97.7 | 97.1 | 97.8 |
| Apartment for Sale | 104.6 | 106.4 | 102.9 | 99.7 | 96.4 | 95.9 | 94.3 |
| Big Flat for Sale | 106.3 | 106.6 | 103.2 | 98.8 | 98.7 | 94.4 | 91.9 |
| Land for Sale | 107.5 | 107.3 | 105.2 | 92.4 | 91.4 | 95.9 | 92.0 |
| Listings (all) | 18,165 | 17,246 | 25,843 | 22,139 | 19,639 | 17,446 | 19,263 |
- Q4 2025 was the break. All four main categories fell 3–12% that quarter, straight after a Q3 2025 listing surge (+50% QoQ in volume).
- Apartment and Big Flat are still falling. Big Flat had a second leg down in Q2 2026 (−4.4%) and fell again in Q3 2026 (−2.6%).
- Villa has stabilized. Its index has held at about 97–98 for four quarters.
- Land dropped 12% in Q4 2025 and has moved sideways since then (a Q2 2026 rebound of +4.9% was followed by −4.1%).
SQL Query
Section titled “SQL Query”-- Same base / bounds / trimmed CTEs as abovecq AS ( SELECT district_id, category, q, avg(price) p, count() n FROM trimmed GROUP BY 1, 2, 3),panel AS ( SELECT district_id, category, sum(n) w, sum(p * n) / sum(n) ref FROM cq GROUP BY 1, 2 HAVING count() = 7 AND min(n) >= 10),j AS ( SELECT cq.category AS cat, cq.q AS q, cq.p AS p, cq.n AS n, panel.w AS w, panel.ref AS ref FROM cq JOIN panel ON panel.district_id = cq.district_id AND panel.category = cq.category JOIN sadb_categories c FINAL ON cq.category = c.category_id WHERE positionCaseInsensitive(c.name_en, 'rent') = 0 -- sale categories),r AS ( SELECT cat, q, if( cat = 2, 100 * exp(sum(w * log(p / ref)) / sum(w)), -- Land: geometric 100 * sum(w * p / ref) / sum(w) ) idx, sum(n) nq FROM j WHERE cat IN (2, 3, 6, 22) GROUP BY cat, q UNION ALL SELECT 0 AS cat, q, 100 * sum(w * p / ref) / sum(w) idx, sum(n) nq FROM j GROUP BY q)SELECT cat, arrayMap( x -> round(x.2, 1), arraySort(groupArray((q, idx))) ) idx_by_quarter, arrayMap(x -> x.2, arraySort(groupArray((q, nq)))) listings_by_quarterFROM rGROUP BY catORDER BY cat -- QoQ = idx[i] / idx[i-1] - 1; Cumulative = idx[Q3'26] / idx[Q1'25] - 1; YoY = idx[Q3'26] / idx[Q3'25] - 1Top Districts per Category
Section titled “Top Districts per Category”The 8 highest-volume panel districts per category. The columns are average asking prices (SAR) per quarter. Δ is Q3 2026 vs Q1 2025, and YoY is Q3 2026 vs Q3 2025.
Villa for Sale
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| Al Mahdiyah | 9,427 | 2,491,478 | 2,567,059 | 2,514,004 | +0.9% | −2.1% |
| An Narjis | 5,133 | 4,125,112 | 3,815,762 | 3,453,870 | −16.3% | −9.5% |
| Ar Rimal | 4,777 | 2,122,554 | 2,245,994 | 2,045,608 | −3.6% | −8.9% |
| Tuwaiq | 3,315 | 1,297,740 | 1,324,428 | 1,321,175 | +1.8% | −0.2% |
| Al Arid | 3,054 | 3,437,694 | 3,351,355 | 2,937,453 | −14.6% | −12.4% |
| Al Janadriyah | 2,010 | 1,515,704 | 1,343,439 | 1,349,571 | −11.0% | +0.5% |
| Al Munsiyah | 1,716 | 2,946,684 | 2,952,515 | 2,894,343 | −1.8% | −2.0% |
| Dhahrat Laban | 1,630 | 2,145,552 | 2,249,157 | 2,142,331 | −0.2% | −4.7% |
Apartment for Sale
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| Al Mahdiyah | 4,411 | 886,696 | 895,243 | 789,258 | −11.0% | −11.8% |
| Ar Rimal | 2,549 | 818,228 | 820,536 | 748,695 | −8.5% | −8.8% |
| An Narjis | 2,099 | 1,294,811 | 1,265,802 | 1,208,939 | −6.6% | −4.5% |
| Al Malqa | 1,642 | 1,470,987 | 1,429,489 | 1,303,010 | −11.4% | −8.8% |
| Dhahrat Laban | 1,611 | 806,650 | 759,945 | 739,388 | −8.3% | −2.7% |
| Al Arid | 1,490 | 1,236,978 | 1,226,420 | 1,113,846 | −10.0% | −9.2% |
| Tuwaiq | 1,479 | 672,599 | 683,507 | 585,452 | −13.0% | −14.3% |
| Al Munsiyah | 1,440 | 1,131,330 | 1,065,769 | 993,209 | −12.2% | −6.8% |
Big Flat for Sale
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| Tuwaiq | 3,233 | 976,746 | 899,908 | 782,864 | −19.8% | −13.0% |
| Ar Rimal | 3,212 | 1,050,076 | 1,081,304 | 969,614 | −7.7% | −10.3% |
| Al Janadriyah | 2,870 | 914,105 | 840,339 | 735,563 | −19.5% | −12.5% |
| Badr | 2,153 | 669,646 | 660,853 | 626,855 | −6.4% | −5.1% |
| An Narjis | 1,933 | 1,852,898 | 1,860,421 | 1,488,862 | −19.6% | −20.0% |
| Okaz | 1,470 | 710,327 | 710,335 | 645,876 | −9.1% | −9.1% |
| Ash Sharq | 1,462 | 910,667 | 887,254 | 803,563 | −11.8% | −9.4% |
| Al Arid | 1,163 | 1,686,509 | 1,690,552 | 1,363,248 | −19.2% | −19.4% |
Land for Sale
| District | Listings | Q1’25 | Q3’25 | Q3’26 | Δ | YoY |
|---|---|---|---|---|---|---|
| Banban | 3,533 | 1,401,573 | 1,194,519 | 896,453 | −36.0% | −25.0% |
| Ash Sharq | 2,087 | 895,614 | 899,341 | 797,322 | −11.0% | −11.3% |
| Uraidh | 1,873 | 585,303 | 532,878 | 438,425 | −25.1% | −17.7% |
| An Narjis | 1,634 | 5,523,819 | 4,744,834 | 4,642,952 | −15.9% | −2.1% |
| Al Arid | 1,563 | 5,756,923 | 5,592,257 | 4,372,459 | −24.0% | −21.8% |
| Dahiat Namar | 1,533 | 1,127,940 | 1,359,441 | 1,362,196 | +20.8% | +0.2% |
| Al Mahdiyah | 1,430 | 2,780,862 | 2,639,570 | 2,240,482 | −19.4% | −15.1% |
| Ar Rimal | 1,060 | 5,752,842 | 5,779,208 | 5,558,833 | −3.4% | −3.8% |
SQL Query
Section titled “SQL Query”-- Same base / bounds / trimmed / cq / panel CTEs as the category query, with AND l.category IN (2, 3, 6, 22) in basecl AS ( SELECT t.district_id district_id, t.category category, any(panel.w) w, avgIf (price, q = '2025-01-01') a0, avgIf (price, q = '2025-07-01') y0, avgIf (price, q = '2026-07-01') a1 FROM trimmed t JOIN panel USING (district_id, category) GROUP BY 1, 2),r AS ( SELECT cl.*, row_number() OVER ( PARTITION BY category ORDER BY w DESC ) rk FROM cl)SELECT category, d.district_name_en district, w listings, round(a0) q1_25, round(y0) q3_25, round(a1) q3_26, round(100 * (a1 / a0 - 1), 1) delta, round(100 * (a1 / y0 - 1), 1) yoy_q3FROM r JOIN sadb_districts d FINAL ON r.district_id = d.district_idWHERE rk <= 8ORDER BY category, w DESC