Queries · q048 · VP Customer Experience · week 1, night 4
“What are shoppers' product review ratings telling us, and does the pattern echo the dips we see in support CSAT?”
Fictional people at a fictional company, each played by a language-model agent. Who they are and what they are told
The manager, at the start of week 1
Subject: Where I'd like to start — support & shopper experience
Hi Mateo,
Good to have you on this with me. I'm still building my map of the business, so I want to keep this week broad — I'd rather get a solid first read on a few big questions than a deep dive on one. Here's what's on my mind, roughly in priority order:
What I need these for: I'm meeting merchant success and the exec team soon and want a credible, numbers-backed view of shopper experience — not just war stories. I also want to start spotting the two or three things that, if we fixed them, would move the needle most broadly across merchants, rather than chasing individual complaints.
Given the slot constraints, let's prioritize #1 through #3 this week if we can't fit all five — those feel most urgent to me. Happy to talk through any of this before you lock in requests.
Thanks, Daniel
The analyst · week 1, night 4, request 3 of 3
Night 3 confirmed the Studio Vrij story with real operational data: their placed-to-delivered time spiked to 9.3 days avg and 70.1% of shipments took over 7 days in May 2025 alone (vs 0-20% other months, platform average stayed 3-5%) - a genuine single-merchant fulfillment breakdown that explains the ticket spike, not a support-side or platform-wide issue. Useful side-finding: platform-wide % of shipments over 7 days creeps up in Nov/Dec 2025 (7-12% vs ~3-5% normally) alongside a real volume surge (1600→2600+ shipments/month) - that's consistent with capacity-constrained holiday fulfillment driving the recurring Nov/Dec ticket spikes seen across all three years, which is the platform-level theme Daniel asked about. The returns-by-merchant report is reassuring: resolve time (~7.5-8.5 days) and rejection rates are consistent across merchants regardless of return-rate level (which mostly tracks vertical - apparel/footwear naturally higher, food/beauty lower) - a clean contrast to how much support-speed varies by merchant. CSAT is noisy but its worst months (Dec-23, Dec-24/Jan-25, Jun-25, Dec-25) line up exactly with the ticket volume/slowness spikes already identified, suggesting speed drives satisfaction. This is the last night, so I'm using the 3 slots to: (1) get CSAT by merchant so Daniel can see which merchants are the weakest satisfaction spots (mirroring the support-speed and returns peer reports already in hand), (2) directly quantify the CSAT-vs-resolution-speed relationship platform-wide to turn "slow support hurts satisfaction" from a visual coincidence into a measured one - this is the single clearest "fix this and it moves the needle broadly" argument for the memo, and (3) a first look at product review ratings (priority #5) since there's room, to see if it echoes the CSAT dips or reveals a blind spot in ticket data.
The engineer · 2 dry runs on the empty schema, then the submission
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating, t.is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT TO_CHAR(t0.month_start, 'YYYY-MM') AS month, t0.review_count AS reviews_submitted, t1.avg_rating, t2.median_rating, t3.pct_low_rating, t3.pct_high_rating, t3.pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, ROUND(AVG(rating)::numeric, 2) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating)::numeric, 1) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_low_rating, ROUND(100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_high_rating, ROUND(100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating, t.is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01')SELECT TO_CHAR(t0.month_start, 'YYYY-MM') AS month, strftime(t0.month_start, '%Y-%m') AS month, t0.review_count AS reviews_submitted, t1.avg_rating, t2.median_rating, t3.pct_low_rating, t3.pct_high_rating, t3.pct_verified_purchaseFROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start) t0JOIN ( SELECT month_start, ROUND(AVG(rating)::numeric, 2) AS avg_rating FROM base GROUP BY month_start) t1 ON t1.month_start = t0.month_startJOIN ( SELECT month_start, ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating)::numeric, 1) AS median_rating FROM base GROUP BY month_start) t2 ON t2.month_start = t0.month_startJOIN ( SELECT month_start, ROUND(100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_low_rating, ROUND(100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_high_rating, ROUND(100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_verified_purchase FROM base GROUP BY month_start) t3 ON t3.month_start = t0.month_startORDER BY t0.month_start ASC
“Query compiles with the expected columns. Submitting now.”
“Submitted. The report delivers the monthly product-review trend exactly as specified — reviews submitted, avg/median rating, % low (1–2★), % high (4–5★), and % verified purchase, approved reviews only, Jan 2023–Dec 2025 (36 rows). I left the CSAT comparison out of this report since mixing a support metric into a reviews-grain table would bundle two questions into one report; that's flagged in the submit note in case Mateo wants a dedicated follow-up report for it.”
As Mateo Ruiz saw it, from the small dataset the agents worked on
month | reviews_submitted | avg_rating | median_rating | pct_low_rating | pct_high_rating | pct_verified_purchase --------+-------------------+------------+---------------+----------------+-----------------+---------------------- 2023-01 | 31 | 4.03 | 5.0 | 16.1 | 67.7 | 100.0 2023-02 | 90 | 3.82 | 4.0 | 21.1 | 64.4 | 100.0 2023-03 | 73 | 3.85 | 5.0 | 23.3 | 63.0 | 100.0 2023-04 | 107 | 3.97 | 5.0 | 18.7 | 64.5 | 100.0 2023-05 | 117 | 4.05 | 5.0 | 17.9 | 68.4 | 100.0 2023-06 | 113 | 3.92 | 5.0 | 21.2 | 66.4 | 100.0 2023-07 | 92 | 4.08 | 5.0 | 15.2 | 68.5 | 100.0 2023-08 | 130 | 4.07 | 5.0 | 14.6 | 72.3 | 100.0 2023-09 | 132 | 4.10 | 5.0 | 14.4 | 68.9 | 100.0 2023-10 | 158 | 3.99 | 5.0 | 19.0 | 66.5 | 100.0 2023-11 | 146 | 4.11 | 5.0 | 13.0 | 69.9 | 100.0 2023-12 | 308 | 3.81 | 5.0 | 22.7 | 62.0 | 100.0 2024-01 | 219 | 4.13 | 5.0 | 14.2 | 72.1 | 100.0 2024-02 | 192 | 4.12 | 5.0 | 12.0 | 71.9 | 100.0 2024-03 | 189 | 4.18 | 5.0 | 12.7 | 73.0 | 100.0 2024-04 | 164 | 4.11 | 5.0 | 15.2 | 70.7 | 100.0 2024-05 | 142 | 4.16 | 5.0 | 12.0 | 73.2 | 100.0 2024-06 | 197 | 4.15 | 5.0 | 12.2 | 72.6 | 100.0 2024-07 | 188 | 4.06 | 5.0 | 15.4 | 69.7 | 100.0 2024-08 | 169 | 4.06 | 5.0 | 16.0 | 71.0 | 100.0 2024-09 | 173 | 4.19 | 5.0 | 11.0 | 73.4 | 100.0 2024-10 | 187 | 4.10 | 5.0 | 14.4 | 67.9 | 100.0 2024-11 | 230 | 4.02 | 5.0 | 18.3 | 68.3 | 100.0 2024-12 | 392 | 3.94 | 5.0 | 16.1 | 65.8 | 100.0 2025-01 | 310 | 3.93 | 5.0 | 19.7 | 65.2 | 100.0 2025-02 | 197 | 4.09 | 5.0 | 14.2 | 69.0 | 100.0 2025-03 | 204 | 4.11 | 5.0 | 12.7 | 70.6 | 100.0 2025-04 | 205 | 4.07 | 5.0 | 15.1 | 70.7 | 100.0 2025-05 | 205 | 4.07 | 5.0 | 15.6 | 72.2 | 100.0 2025-06 | 217 | 3.89 | 5.0 | 20.3 | 63.1 | 100.0 2025-07 | 161 | 4.07 | 5.0 | 15.5 | 70.8 | 100.0 2025-08 | 224 | 4.21 | 5.0 | 13.4 | 73.7 | 100.0 2025-09 | 188 | 3.96 | 4.0 | 14.9 | 67.6 | 100.0 2025-10 | 245 | 4.16 | 5.0 | 12.2 | 71.8 | 100.0 2025-11 | 258 | 4.23 | 5.0 | 12.8 | 73.6 | 100.0 2025-12 | 454 | 3.71 | 4.0 | 25.8 | 59.5 | 100.0 (36 rows)
The memo and the queries that followed; links found by title, so inferred
It builds on:
Changed only where the benchmark needs the same result on every system
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating, t.is_verified_purchase t.rating AS rating, t.is_verified_purchase AS is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01')SELECT strftime(t0.month_start, '%Y-%m') AS month, {{year_month(t0.month_start)}} AS month, t0.review_count AS reviews_submitted, t1.avg_rating, t2.median_rating, t3.pct_low_rating, t3.pct_high_rating, t3.pct_verified_purchase t1.avg_rating AS avg_rating, t2.median_rating AS median_rating, t3.pct_low_rating AS pct_low_rating, t3.pct_high_rating AS pct_high_rating, t3.pct_verified_purchase AS pct_verified_purchaseFROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start) t0JOIN ( SELECT month_start, ROUND(AVG(rating)::numeric, 2) AS avg_rating SELECT month_start, AVG(CAST(rating AS NUMERIC(18,6))) AS avg_rating FROM base GROUP BY month_start) t1 ON t1.month_start = t0.month_startJOIN ( SELECT month_start, ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating)::numeric, 1) AS median_rating SELECT month_start, {{percentile_cont(0.5, rating)}} AS median_rating FROM base GROUP BY month_start) t2 ON t2.month_start = t0.month_startJOIN ( SELECT month_start, ROUND(100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_low_rating, ROUND(100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_high_rating, ROUND(100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_verified_purchase 100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*) AS pct_low_rating, 100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*) AS pct_high_rating, 100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*) AS pct_verified_purchase FROM base GROUP BY month_start) t3 ON t3.month_start = t0.month_startORDER BY t0.month_start ASCORDER BY t0.month_start ASC NULLS LAST
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating AS rating, t.is_verified_purchase AS is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT strftime(t0.month_start, '%Y-%m') AS month, t0.review_count AS reviews_submitted, t1.avg_rating AS avg_rating, t2.median_rating AS median_rating, t3.pct_low_rating AS pct_low_rating, t3.pct_high_rating AS pct_high_rating, t3.pct_verified_purchase AS pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, AVG(CAST(rating AS NUMERIC(18,6))) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, 100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*) AS pct_low_rating, 100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*) AS pct_high_rating, 100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC NULLS LAST
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating AS rating, t.is_verified_purchase AS is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT to_char(t0.month_start, 'YYYY-MM') AS month, t0.review_count AS reviews_submitted, t1.avg_rating AS avg_rating, t2.median_rating AS median_rating, t3.pct_low_rating AS pct_low_rating, t3.pct_high_rating AS pct_high_rating, t3.pct_verified_purchase AS pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, AVG(CAST(rating AS NUMERIC(18,6))) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, 100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*) AS pct_low_rating, 100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*) AS pct_high_rating, 100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC NULLS LAST
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating AS rating, t.is_verified_purchase AS is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT to_char(CAST(t0.month_start AS timestamp), 'YYYY-MM') AS month, t0.review_count AS reviews_submitted, t1.avg_rating AS avg_rating, t2.median_rating AS median_rating, t3.pct_low_rating AS pct_low_rating, t3.pct_high_rating AS pct_high_rating, t3.pct_verified_purchase AS pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, AVG(CAST(rating AS NUMERIC(18,6))) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, 100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*) AS pct_low_rating, 100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*) AS pct_high_rating, 100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC NULLS LAST
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating AS rating, t.is_verified_purchase AS is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT to_char(t0.month_start, 'YYYY-MM') AS month, t0.review_count AS reviews_submitted, t1.avg_rating AS avg_rating, t2.median_rating AS median_rating, t3.pct_low_rating AS pct_low_rating, t3.pct_high_rating AS pct_high_rating, t3.pct_verified_purchase AS pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, AVG(CAST(rating AS NUMERIC(18,6))) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY CAST(rating AS DOUBLE PRECISION)) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, 100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*) AS pct_low_rating, 100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*) AS pct_high_rating, 100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC NULLS LAST
WITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating AS rating, t.is_verified_purchase AS is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT formatDateTime(t0.month_start, '%Y-%m') AS month, t0.review_count AS reviews_submitted, t1.avg_rating AS avg_rating, t2.median_rating AS median_rating, t3.pct_low_rating AS pct_low_rating, t3.pct_high_rating AS pct_high_rating, t3.pct_verified_purchase AS pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, AVG(CAST(rating AS NUMERIC(18,6))) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, quantileExactInclusive(0.5)(toFloat64(rating)) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, 100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*) AS pct_low_rating, 100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*) AS pct_high_rating, 100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC NULLS LAST
The agents' own records, as the role play wrote them; only the personal data of the person who ran it is redacted
Report request from Mateo Ruiz (analyst for the VP Customer Experience): Title: Product review ratings trend, monthly Question: What are shoppers' product review ratings telling us, and does the pattern echo the dips we see in support CSAT? Grain: one calendar month, platform-wide Columns: - month (YYYY-MM) - reviews submitted - avg rating (1-5) - median rating (1-5) - % low rating (1-2 stars) - % high rating (4-5 stars) - % verified purchase Details: Source: product_reviews. Grain the month on created_at. Window: 2023-01-01 through 2025-12-31 (36 months). Only include is_approved = true reviews (published ones actually shown to shoppers). avg/median rating over product_reviews.rating. '% low rating' = rating in (1,2) count / total reviews that month, percentage rounded to 1 decimal; '% high rating' = rating in (4,5) count / total, percentage rounded to 1 decimal. '% verified purchase' = is_verified_purchase=true count / total reviews that month, percentage rounded to 1 decimal. Round avg rating to 2 decimals, median to 1 decimal. Order by month ascending. Check your query with the warehouse's dry_run tool, then hand it in with submit.
dry_runWITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating, t.is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT TO_CHAR(t0.month_start, 'YYYY-MM') AS month, t0.review_count AS reviews_submitted, t1.avg_rating, t2.median_rating, t3.pct_low_rating, t3.pct_high_rating, t3.pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, ROUND(AVG(rating)::numeric, 2) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating)::numeric, 1) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_low_rating, ROUND(100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_high_rating, ROUND(100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC
STATUS: REJECTED - does not compile: Catalog Error: Scalar Function with name to_char does not exist!
dry_runWITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating, t.is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT strftime(t0.month_start, '%Y-%m') AS month, t0.review_count AS reviews_submitted, t1.avg_rating, t2.median_rating, t3.pct_low_rating, t3.pct_high_rating, t3.pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, ROUND(AVG(rating)::numeric, 2) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating)::numeric, 1) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_low_rating, ROUND(100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_high_rating, ROUND(100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC
STATUS: COMPILES (dry run on the empty schema, no data read) COLUMNS: month, reviews_submitted, avg_rating, median_rating, pct_low_rating, pct_high_rating, pct_verified_purchase
submitWITH base AS ( SELECT date_trunc('month', t.created_at) AS month_start, t.rating, t.is_verified_purchase FROM product_reviews t WHERE t.is_approved = true AND t.created_at >= DATE '2023-01-01' AND t.created_at < DATE '2026-01-01' ) SELECT strftime(t0.month_start, '%Y-%m') AS month, t0.review_count AS reviews_submitted, t1.avg_rating, t2.median_rating, t3.pct_low_rating, t3.pct_high_rating, t3.pct_verified_purchase FROM ( SELECT month_start, COUNT(*) AS review_count FROM base GROUP BY month_start ) t0 JOIN ( SELECT month_start, ROUND(AVG(rating)::numeric, 2) AS avg_rating FROM base GROUP BY month_start ) t1 ON t1.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY rating)::numeric, 1) AS median_rating FROM base GROUP BY month_start ) t2 ON t2.month_start = t0.month_start JOIN ( SELECT month_start, ROUND(100.0 * SUM(CASE WHEN rating IN (1,2) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_low_rating, ROUND(100.0 * SUM(CASE WHEN rating IN (4,5) THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_high_rating, ROUND(100.0 * SUM(CASE WHEN is_verified_purchase THEN 1 ELSE 0 END) / COUNT(*), 1) AS pct_verified_purchase FROM base GROUP BY month_start ) t3 ON t3.month_start = t0.month_start ORDER BY t0.month_start ASC
Submitted to tonight's batch. Your work on this request is done.