SQL新手求助:如何聚合州级门票销量数据并找出时间维度下的最大绝对变化
Hey there! Let's walk through how to solve this SQL problem step by step. I know you're just starting out, so I'll keep things clear and explain each part along the way.
First, Let's Outline the Plan
Your requirements boil down to three key steps:
- Calculate total daily ticket sales per state (summing across all vendors)
- For each state, find the date with the highest total sales and the date with the lowest total sales (plus their respective values)
- Compute the absolute difference between those high and low values, then rank states by this difference (top 3, descending)
The SQL Code
Here's a complete query that does exactly what you need, optimized for readability and performance (great for large datasets):
WITH daily_state_sales AS ( -- Step 1: Aggregate total sales per state per day SELECT state_key, sell_date, SUM(no_of_sales) AS total_sales FROM ticket_sales GROUP BY state_key, sell_date ), state_sales_ranked AS ( -- Step 2: Rank each state's daily sales to find highest/lowest SELECT state_key, sell_date, total_sales, -- Rank sales from highest to lowest (1 = top) ROW_NUMBER() OVER (PARTITION BY state_key ORDER BY total_sales DESC) AS rn_max, -- Rank sales from lowest to highest (1 = bottom) ROW_NUMBER() OVER (PARTITION BY state_key ORDER BY total_sales ASC) AS rn_min FROM daily_state_sales ) -- Step 3: Combine results, calculate difference, and get top 3 states SELECT st.state_name, MAX(CASE WHEN ssr.rn_max = 1 THEN ssr.sell_date END) AS date_max, MAX(CASE WHEN ssr.rn_max = 1 THEN ssr.total_sales END) AS sales_max, MAX(CASE WHEN ssr.rn_min = 1 THEN ssr.sell_date END) AS date_min, MAX(CASE WHEN ssr.rn_min = 1 THEN ssr.total_sales END) AS sales_min, ABS( MAX(CASE WHEN ssr.rn_max = 1 THEN ssr.total_sales END) - MAX(CASE WHEN ssr.rn_min = 1 THEN ssr.total_sales END) ) AS difference FROM state_sales_ranked ssr JOIN state_table st ON ssr.state_key = st.state_key GROUP BY st.state_name ORDER BY difference DESC LIMIT 3;
Let's Break Down Each Part
daily_state_salesCTE
This first common table expression (CTE) groups sales by state and date, summing up all vendor sales for each combination. This gives us the total daily sales per state, which is the foundation of our analysis.state_sales_rankedCTE
Here we use window functions (a powerful SQL tool for group-wise calculations) to rank each state's daily sales:ROW_NUMBER() OVER (PARTITION BY state_key ORDER BY total_sales DESC)assigns a rank of 1 to the day with the highest sales for each state.ROW_NUMBER() OVER (PARTITION BY state_key ORDER BY total_sales ASC)assigns a rank of 1 to the day with the lowest sales for each state.
Note: If multiple days have the same highest/lowest sales,ROW_NUMBER()will pick one randomly. If you want to keep all ties, replace it withRANK().
Main Query
- We use
CASE WHENto filter out the highest-ranked (rn_max=1) and lowest-ranked (rn_min=1) records for each state, grabbing their dates and sales values. ABS()ensures we get the absolute difference between high and low sales (so both increases and decreases are counted as positive volatility).- We join with
state_tableto get the state names instead of just keys, then group by state name, sort by difference descending, and limit to the top 3 results.
- We use
Why This Works for Large Datasets
Window functions are far more efficient than nested subqueries for this kind of group-wise ranking, which is perfect for your real-world scenario with large tables. CTEs also make the query easy to read and modify later if you need to adjust logic.
Testing Against Your Sample Data
When you run this query with your sample tables, it will output exactly the results you expected:
| state_name | date_max | sales_max | date_min | sales_min | difference |
|---|---|---|---|---|---|
| Maine | 2021-03-01 | 113 | 2021-02-01 | 39 | 74 |
| Connecticut | 2021-03-01 | 128 | 2021-02-01 | 73 | 55 |
| Alabama | 2021-03-01 | 87 | 2021-01-01 | 58 | 29 |
内容的提问来源于stack exchange,提问作者Martha's Vineyard

