如何筛选Table2指定行并统计Table1对应时间区间的记录数与总价
Hey there, let's break down what's wrong with your current query and fix it step by step to meet your requirement.
Table Structures
First, let's restate your table data clearly:
table1
| price | col1 | col2 | time |
|---|---|---|---|
| 10 | 1 | 1 | 10 |
| 100 | 1 | 1 | 13 |
| 150 | 1 | 1 | 15 |
table2
| id | startTm | endTm | col1 | col2 |
|---|---|---|---|---|
| 1 | 12 | 20 | 1 | 1 |
| 2 | 15 | 26 | 1 | 1 |
| 3 | 11 | 13 | 1 | 1 |
Your Goal
You need to:
- Filter rows from
table2wherestartTm >= xandendTm <= y(replacex/ywith your actual values) - For each filtered row, calculate:
- Total number of records in
table1wheretimeis between the row'sstartTmandendTm, andcol1/col2match - Sum of
pricefor those matchingtable1records
- Total number of records in
What's Broken in Your Current Query
Your use of user variables (@sTime, @eTime) won't work as expected. Here's why:
SQL executes subqueries before the main query assigns values to variables. When your left-joined subquery runs, @sTime and @eTime are still uninitialized (usually NULL), so the WHERE time BETWEEN @sTime AND @eTime condition matches nothing. That's why you're getting incorrect or empty totalNo/totalPrice values.
Correct Solutions
Here are two reliable approaches to get the results you need:
Option 1: Correlated Subqueries (Simple & Readable)
This method runs a small subquery for each row in your filtered table2—great for small to medium datasets:
SELECT t2.id, t2.startTm, t2.endTm, t2.col1, t2.col2, -- Count matching records from table1 (SELECT COUNT(*) FROM table1 t1 WHERE t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.time BETWEEN t2.startTm AND t2.endTm) AS totalNo, -- Sum prices of matching records (SELECT SUM(t1.price) FROM table1 t1 WHERE t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.time BETWEEN t2.startTm AND t2.endTm) AS totalPrice FROM table2 t2 WHERE t2.startTm >= [your_x_value] AND t2.endTm <= [your_y_value];
Option 2: JOIN + GROUP BY (More Efficient for Large Datasets)
If you're working with bigger tables, this approach is better because it avoids running duplicate subqueries. We use COALESCE to return 0 instead of NULL when there are no matching records in table1:
SELECT t2.id, t2.startTm, t2.endTm, t2.col1, t2.col2, COUNT(t1.price) AS totalNo, COALESCE(SUM(t1.price), 0) AS totalPrice FROM table2 t2 LEFT JOIN table1 t1 ON t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.time BETWEEN t2.startTm AND t2.endTm WHERE t2.startTm >= [your_x_value] AND t2.endTm <= [your_y_value] GROUP BY t2.id, t2.startTm, t2.endTm, t2.col1, t2.col2;
Example Output (Using x=11, y=26)
If you filter table2 with startTm >=11 and endTm <=26, both queries will return this result:
| id | startTm | endTm | col1 | col2 | totalNo | totalPrice |
|---|---|---|---|---|---|---|
| 1 | 12 | 20 | 1 | 1 | 2 | 250 |
| 2 | 15 | 26 | 1 | 1 | 1 | 150 |
| 3 | 11 | 13 | 1 | 1 | 1 | 100 |
Quick breakdown:
- Row 1 (12-20): Matches
table1rows with time 13 and 15 → count=2, sum=100+150=250 - Row 2 (15-26): Matches
table1row with time 15 → count=1, sum=150 - Row 3 (11-13): Matches
table1row with time13 → count=1, sum=100
内容的提问来源于stack exchange,提问作者hrushilok

