Reputation: 205
I want to write a query which returns all rows until the sum of one of the columns value reaches a certain value.
For example in the table below:
DATE ETC Meeting
2013-02-01 00:00:00 85482 1
2013-02-01 00:00:00 47228 2
2013-02-02 00:00:00 12026 4
2013-02-03 00:00:00 78927 6
2013-02-04 00:00:00 85662 2
2013-03-05 00:00:00 47978 1
2013-08-07 00:00:00 8582 1
If I want to get the rows until the sum of column Meeting
equals 7.
DATE ETC Meeting
2013-02-01 00:00:00 85482 1
2013-02-01 00:00:00 47228 2
2013-02-02 00:00:00 12026 4
If I want to get the rows until the sum of column Meeting
equals 13.
DATE ETC Meeting
2013-02-01 00:00:00 85482 1
2013-02-01 00:00:00 47228 2
2013-02-02 00:00:00 12026 4
2013-02-03 00:00:00 78927 6
Upvotes: 14
Views: 22697
Reputation: 1341
This one outperforms all.
SET @runningTotal=0;
SELECT
O.Id,
O.Type,
O.MyAmountCol,
@runningTotal + O.MyAmountCol as 'RunningTotal',
@runningTotal := @runningTotal + O.MyAmountCol
FROM Table1 O
HAVING RunningTotal <=7;
Take a look at execution plans for both queries.
Upvotes: 6
Reputation:
As no DBMS is given, the following is an ANSI SQL solution which works on a wide range of DBMS:
select *
from (
select date_column,
etc,
sum(Meeting) over (order by date_column asc) run_sum
from meetings
) t
where run_sum <= 7
order by date_column asc;
(I used the column name date_column
instead of date
because DATE
is a reserved word in SQL and should not be used as a column name to avoid problems)
Upvotes: 1
Reputation: 2527
Here's a way which should work in MySQL :
SELECT
O.Id,
O.Type,
O.MyAmountCol,
(SELECT
sum(MyAmountCol) FROM Table1
WHERE Id <= O.Id) 'RunningTotal'
FROM Table1 O
HAVING RunningTotal <= 7
It involves calculating a running total and selecting records while the running total is less than or equal to the given number, in this case 7
.
Upvotes: 9
Reputation: 2002
Here's a way to do it without a stored procedure:
SET @msum := 0;
SELECT t1.*
FROM (
SELECT m.*,
(@msum := @msum + m.meetings) AS cumulative_meetings
FROM meetings m
ORDER BY m.date ASC
) t1
WHERE t1.cumulative_meetings <= 7;
Upvotes: 9
Reputation: 402
In Oracle, I think you can use the SUM analytic function. You can refer here: http://www.adp-gmbh.ch/ora/sql/analytical/sum.html
Upvotes: 0
Reputation: 738
Hemant you do not state the RDBMS that use. Here is a script in t-sql that you can use in order to solve your problem.
DECLARE @numberToReach INT;
SET @numberToReach = 10; --you can change this
DECLARE @date DATETIME;
DECLARE @etc VARCHAR(20);
DECLARE @meeting INT;
DECLARE @temp_sum INT;
CREATE TABLE #tempTable
(
Dates DATETIME,
Etcs VARCHAR(20),
Meeting INT,
)
DECLARE tempcursor CURSOR FOR
SELECT *
FROM YourTABLENAME
OPEN tempcursor;
FETCH NEXT FROM tempcursor INTO @date, @etc, @meeting;
WHILE(@@FETCH_STATUS = 0)
BEGIN
SET @temp_sum = @temp_sum + @meeting;
IF @temp_sum < @numberToReach
BEGIN
INSERT INTO #tempTable
(
Dates,
Etcs,
Meeting
)
VALUES
(
@date,
@etc,
@meeting
)
FETCH NEXT FROM tempcursor INTO @date, @etc, @meeting;
END
END
SELECT * FROM #tempTable
CLOSE tempcursor
DEALLOCATE tempcursor
DROP TABLE #tempTable
Upvotes: 1
Reputation: 116478
Here's an ugly way:
SELECT *
FROM meetings m1
WHERE (SELECT SUM(m2.Meeting)
FROM meetings m2
WHERE m2.DATE < m1.DATE OR (m2.DATE = m1.DATE AND m2.ETC >= m1.ETC)) <= 7
The ordering is based on DATE
first, then ETC
in descending order, since that seems to be what we have to go on. Note that if that is not unique, you will get the wrong result.
Upvotes: 0