SQL Query Generation

Code GenerationDifficulty: MEDIUM11 models comparedTotal cost: $0.019947

Prompt

Write a SQL query (PostgreSQL) to find customers who made purchases in every month of 2024. Tables:
- customers(id, name, email)
- orders(id, customer_id, amount, created_at)

Return customer name and their total 2024 spend, ordered by spend descending.

Model Responses

Claude Opus 4.6

Unrated
11,787ms602 tokens
```sql SELECT c.name, SUM(o.amount) AS total_spend FROM customers c JOIN orders o ON o.customer_id = c.id WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' GROUP BY c.id, c.name HAVING COUNT(DISTINCT EXTRACT(MONTH FROM o.created_at)) = 12 ORDER BY total_spend DESC; ``` ## How It Works ### Step-by-step breakdown: 1. **JOIN** `customers` with `orders` to link each order to its customer. 2. **WHERE** clause filters orders to only those within the year 2024. Using `>= '2024-01-01'` and `< '2025-01-01'` is index-friendly and avoids edge cases with timestamps (e.g., `2024-12-31 23:59:59` wouldn't be missed). 3. **GROUP BY** `c.id, c.name` aggregates all 2024 orders per customer. Including `c.id` ensures correctness if two customers share the same name. 4. **HAVING** clause is the core filter: - `EXTRACT(MONTH FROM o.created_at)` pulls the month number (1–12) - `COUNT(DISTINCT ...)` counts how many *unique* months the customer ordered in - `= 12` ensures they purchased in **all 12 months** 5. **SUM(o.amount)** calculates total 2024 spend. 6. **ORDER BY total_spend DESC** ranks the most valuable customers first. ### Example result: | name | total_spend | |---------------|-------------| | Alice Johnson | 15,240.00 | | Bob Smith | 9,870.50 | | Carol White | 7,330.25 | ### Edge case note: If `created_at` is a `DATE` type rather than `TIMESTAMP`, the query works identically. If it includes timezone info (`TIMESTAMPTZ`), the `EXTRACT` function operates on the session timezone — consider using `AT TIME ZONE` if timezone precision matters.

GPT-4.1

Unrated
4,235ms381 tokens
Certainly! To find customers who made **at least one purchase in every month of 2024**, we need to: 1. Join `customers` and `orders`. 2. Filter for orders in 2024. 3. Group by customer, count distinct months. 4. Require 12 months per customer (i.e., they purchased each month). 5. Sum their total spend. 6. Return their name and total spend, ordered descending. Here’s the SQL query: ```sql SELECT c.name, SUM(o.amount) AS total_2024_spend FROM customers c JOIN orders o ON o.customer_id = c.id WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' GROUP BY c.id, c.name HAVING COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) = 12 ORDER BY total_2024_spend DESC; ``` **Explanation:** - `DATE_TRUNC('month', o.created_at)`: Extracts the month part (e.g., 2024-01-01) for counting unique months. - `HAVING COUNT(DISTINCT ...) = 12`: Ensures the customer made a purchase in every month. - Sums `o.amount` for their total 2024 spend. - Results are ordered by total spend, descending. Let me know if you need to include customer email or other info!

GPT-4.1 Mini

Unrated
7,395ms476 tokens
Here's a SQL query for PostgreSQL that finds customers who made purchases in **every month of 2024** and returns their name along with their total spend in 2024, ordered by total spend descending: ```sql WITH monthly_purchases AS ( SELECT customer_id, DATE_TRUNC('month', created_at) AS month FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01' GROUP BY customer_id, month ), months_2024 AS ( SELECT generate_series('2024-01-01'::date, '2024-12-01'::date, interval '1 month') AS month ), customers_all_months AS ( SELECT mp.customer_id FROM monthly_purchases mp GROUP BY mp.customer_id HAVING COUNT(DISTINCT mp.month) = 12 ) SELECT c.name, SUM(o.amount) AS total_2024_spend FROM customers c JOIN orders o ON c.id = o.customer_id JOIN customers_all_months cam ON c.id = cam.customer_id WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' GROUP BY c.id, c.name ORDER BY total_2024_spend DESC; ``` ### Explanation: 1. **monthly_purchases**: Finds each customer's distinct purchase months in 2024. 2. **months_2024**: Generates all months in 2024 (used if needed, but here I went with count of distinct months). 3. **customers_all_months**: Filters customers who have purchases in all 12 months of 2024. 4. Finally, join back with `customers` and `orders` to compute total spend and return customer name and total spend, ordered by spend descending. Let me know if you want to include email or additional info!

GPT-4.1 Nano

Unrated
3,131ms543 tokens
Certainly! To find customers who made purchases in every month of 2024, you need to: 1. Identify customers who have orders in *all* months of 2024. 2. Sum their total spending in 2024. Here's a step-by-step approach: - Generate all months of 2024. - Find customers who have at least one order in *each* of these months. - Sum their total spend. Here's the PostgreSQL query: ```sql WITH months_2024 AS ( SELECT generate_series('2024-01-01'::date, '2024-12-01'::date, interval '1 month') AS month_start ), customer_months AS ( SELECT DISTINCT o.customer_id, DATE_TRUNC('month', o.created_at) AS order_month FROM orders o WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' ), customers_in_all_months AS ( SELECT cm.customer_id FROM customer_months cm GROUP BY cm.customer_id HAVING COUNT(DISTINCT cm.order_month) = 12 ) SELECT c.name, SUM(o.amount) AS total_spent_2024 FROM customers c JOIN customers_in_all_months cim ON c.id = cim.customer_id JOIN orders o ON c.id = o.customer_id WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' GROUP BY c.id, c.name ORDER BY total_spent_2024 DESC; ``` **Explanation:** - `months_2024`: generates all months of 2024, though in this version, we mainly rely on counting distinct months from orders. - `customer_months`: finds each customer's order months. - `customers_in_all_months`: customers with orders in all 12 months. - The final `SELECT` joins to get customer info, sums their 2024 orders, and orders the results by total spend descending. This query returns the names of customers who made purchases every month in 2024 along with their total spending for that year.

o3

Unrated
8,353ms837 tokens
```sql /* customers that bought something in every month of 2024 together with their total 2024 spend, highest spend first */ WITH sales_2024 AS ( SELECT o.customer_id, o.amount, date_trunc('month', o.created_at) AS order_month FROM orders o -- Predicate written so indexes on created_at can be used WHERE o.created_at >= DATE '2024-01-01' AND o.created_at < DATE '2025-01-01' ) SELECT c.name, SUM(s.amount) AS total_spend_2024 FROM customers c JOIN sales_2024 s ON s.customer_id = c.id GROUP BY c.id, c.name HAVING COUNT(DISTINCT s.order_month) = 12 -- at least one order in each month ORDER BY total_spend_2024 DESC; ``` Explanation 1. `sales_2024` keeps only 2024 orders and pre-computes the month (`date_trunc('month', …)`). 2. In the final query we • join those sales to `customers`, • aggregate by customer, • keep only those whose `COUNT(DISTINCT order_month)` is 12 (one or more orders in every month), • sum the amounts to obtain the 2024 spend, • sort by that spend in descending order.

o3 Mini

Unrated
3,186ms395 tokens
SELECT     c.name,     SUM(o.amount) AS total_2024_spend FROM     customers c JOIN     orders o     ON c.id = o.customer_id WHERE     o.created_at >= '2024-01-01'     AND o.created_at < '2025-01-01' GROUP BY     c.id, c.name HAVING     COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) = 12 ORDER BY     total_2024_spend DESC;

o4 Mini

Unrated
10,482ms944 tokens
Here’s a single‐pass solution using grouping and a “distinct months” check. It filters to 2024, groups by customer, ensures you’ve seen all 12 months, then sums and orders by spend: ```sql SELECT c.name, SUM(o.amount) AS total_2024_spend FROM customers c JOIN orders o ON o.customer_id = c.id WHERE -- only orders in 2024 o.created_at >= DATE '2024-01-01' AND o.created_at < DATE '2025-01-01' GROUP BY c.id, c.name HAVING -- made at least one purchase in each of the 12 months COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) = 12 ORDER BY total_2024_spend DESC; ``` Explanation: 1. The `WHERE` clause restricts to orders in calendar‐year 2024. 2. We `GROUP BY` each customer. 3. `COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) = 12` ensures the customer placed at least one order in each month of 2024. 4. We `SUM(o.amount)` to get their total spend, and finally order by that sum descending.

GPT-4o Mini

Unrated
10,387ms547 tokens$0.000298
To find customers who made purchases in every month of 2024 and to return their names along with their total spend in that year, you can use the following SQL query. This query utilizes Common Table Expressions (CTEs) to break down the problem into manageable parts. ```sql WITH monthly_orders AS ( SELECT customer_id, DATE_TRUNC('month', created_at) AS order_month, SUM(amount) AS total_spent FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01' GROUP BY customer_id, order_month ), customer_months AS ( SELECT customer_id, COUNT(DISTINCT order_month) AS months_count, SUM(total_spent) AS total_spent FROM monthly_orders GROUP BY customer_id HAVING COUNT(DISTINCT order_month) = 12 ) SELECT c.name, cm.total_spent FROM customer_months cm JOIN customers c ON c.id = cm.customer_id ORDER BY cm.total_spent DESC; ``` ### Explanation: 1. **monthly_orders CTE**: This Common Table Expression aggregates the orders by customer and month for the year 2024, calculating the total spent per customer for each month. - It filters the `orders` table to include only the records from 2024. - It groups the result by `customer_id` and the month extracted from `created_at`, summing the `amount` for each group. 2. **customer_months CTE**: This CTE counts the number of unique months in which each customer made purchases and sums up their total spending. - It groups the results from `monthly_orders` by `customer_id`. - The `HAVING` clause ensures that only those customers who have made purchases in all 12 months of 2024 are included. 3. **Final SELECT Statement**: This part of the query joins the results from `customer_months` with the `customers` table to retrieve the customer names and their corresponding total spend. The results are ordered by total spend in descending order. This query should work efficiently in PostgreSQL and yield the desired results.

Claude Haiku 4.5

Unrated
3,607ms523 tokens$0.002311
# SQL Query: Customers with Purchases Every Month in 2024 ```sql SELECT c.name, SUM(o.amount) AS total_spend FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE EXTRACT(YEAR FROM o.created_at) = 2024 GROUP BY c.id, c.name HAVING COUNT(DISTINCT EXTRACT(MONTH FROM o.created_at)) = 12 ORDER BY total_spend DESC; ``` ## How It Works 1. **JOIN**: Connects customers with their orders 2. **WHERE**: Filters for orders placed in 2024 3. **GROUP BY**: Aggregates data by customer 4. **HAVING**: Ensures the customer has purchases in all 12 distinct months - `COUNT(DISTINCT EXTRACT(MONTH FROM ...))` counts unique months - Must equal 12 to include the customer 5. **ORDER BY**: Sorts by total spending in descending order ## Alternative Version (More Explicit) If you prefer clearer logic showing the month requirement: ```sql WITH monthly_purchases AS ( SELECT c.id, c.name, EXTRACT(MONTH FROM o.created_at) AS purchase_month, SUM(o.amount) AS month_total FROM customers c INNER JOIN orders o ON c.id = o.customer_id WHERE EXTRACT(YEAR FROM o.created_at) = 2024 GROUP BY c.id, c.name, EXTRACT(MONTH FROM o.created_at) ) SELECT name, SUM(month_total) AS total_spend FROM monthly_purchases GROUP BY id, name HAVING COUNT(*) = 12 ORDER BY total_spend DESC; ``` Both queries return the same result. Choose based on readability preference!

GPT-4o

Unrated
6,381ms481 tokens$0.004300
To solve this problem, you can use a combination of SQL techniques such as `JOIN`, `GROUP BY`, `HAVING`, and `SUM` functions. The goal is to identify customers who have made purchases in every month of 2024 and calculate their total spend for that year. Here's the SQL query to achieve this: ```sql SELECT c.name, SUM(o.amount) AS total_spend FROM customers c JOIN orders o ON c.id = o.customer_id WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' GROUP BY c.id, c.name HAVING COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) = 12 ORDER BY total_spend DESC; ``` ### Explanation: 1. **Join Tables:** We join the `customers` table with the `orders` table on the `customer_id`. 2. **Filter Orders by Year:** Use the `WHERE` clause to filter orders that were created within the year 2024. This is done by checking if `created_at` is between '2024-01-01' and '2025-01-01'. 3. **Group by Customer:** Use `GROUP BY` to aggregate data by customer ID and name. This enables calculation of total spend and counting of unique months for each customer. 4. **Count Unique Months:** Use `DATE_TRUNC('month', o.created_at)` to truncate dates to the start of the month, and then `COUNT(DISTINCT ...)` to find distinct months. The `HAVING` clause ensures that only customers with orders in all 12 months are returned. 5. **Calculate Total Spend:** Use `SUM(o.amount)` to calculate the total spend of each customer for the year 2024. 6. **Order by Spend:** Finally, order the results by total spend in descending order using the `ORDER BY` clause.

Claude Sonnet 4.6

Unrated
15,313ms930 tokens$0.013038
## SQL Query: Customers Who Purchased Every Month in 2024 ```sql SELECT c.name, SUM(o.amount) AS total_spend FROM customers c JOIN orders o ON o.customer_id = c.id WHERE o.created_at >= '2024-01-01' AND o.created_at < '2025-01-01' GROUP BY c.id, c.name HAVING COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) = 12 ORDER BY total_spend DESC; ``` --- ### How It Works | Clause | Purpose | |--------|---------| | `WHERE` date range | Filters to 2024 orders only using a **sargable** range (avoids wrapping the column in a function, keeping index usability) | | `GROUP BY c.id, c.name` | Groups per customer — using `id` prevents false merges if two customers share a name | | `HAVING COUNT(DISTINCT DATE_TRUNC('month', ...)) = 12` | Counts **distinct months** the customer ordered in; must equal 12 to satisfy "every month" | | `SUM(o.amount)` | Totals spend only within the filtered 2024 rows | --- ### Key Design Decisions **Why `DATE_TRUNC` instead of `EXTRACT(MONTH ...)`?** ```sql -- ❌ EXTRACT alone would conflate months across years -- (irrelevant here due to WHERE clause, but safer habit) COUNT(DISTINCT EXTRACT(MONTH FROM o.created_at)) -- ✅ DATE_TRUNC gives a distinct timestamp per month/year COUNT(DISTINCT DATE_TRUNC('month', o.created_at)) ``` **Why `>= '2025-01-01'` instead of `<= '2024-12-31'`?** ```sql -- ❌ Misses times on the last day (e.g., 2024-12-31 23:59:59) AND o.created_at <= '2024-12-31' -- ✅ Captures the full day and works with any timestamp precision AND o.created_at < '2025-01-01' ``` --- ### Alternative: Using a CTE for Clarity ```sql WITH purchases_2024 AS ( SELECT customer_id, amount, DATE_TRUNC('month', created_at) AS purchase_month FROM orders WHERE created_at >= '2024-01-01' AND created_at < '2025-01-01' ), every_month_customers AS ( SELECT customer_id FROM purchases_2024 GROUP BY customer_id HAVING COUNT(DISTINCT purchase_month) = 12 ) SELECT c.name, SUM(p.amount) AS total_spend FROM every_month_customers emc JOIN customers c ON c.id = emc.customer_id JOIN purchases_2024 p ON p.customer_id = emc.customer_id GROUP BY c.id, c.name ORDER BY total_spend DESC; ``` The CTE version is preferable when the logic needs to be **extended** (e.g., adding per-month breakdowns or joining additional filters). --- ### Recommended Index ```sql -- Covers the WHERE filter and supports the GROUP BY aggregation CREATE INDEX idx_orders_customer_created ON orders (customer_id, created_at); ```

Cost & Performance Comparison

ModelLatencyTokensCostVerdict
Claude Opus 4.611,787ms602
GPT-4.14,235ms381
GPT-4.1 Mini7,395ms476
GPT-4.1 Nano3,131ms543
o38,353ms837
o3 Mini3,186ms395
o4 Mini10,482ms944
GPT-4o Mini10,387ms547$0.000298
Claude Haiku 4.53,607ms523$0.002311
GPT-4o6,381ms481$0.004300
Claude Sonnet 4.615,313ms930$0.013038
SQL Query Generation — Model Lab — AISpendGuard