Sorry if this became a double post.
I am writing a query that determines the number of customers holding shares in a certain fund grouped by each day transactions happened on that fund.
So my transactions table is:
CREATE TABLE trans(
transID SERIAL PRIMARY KEY,
sin CHAR(9) REFERENCES customer(sin) ON UPDATE CASCADE ON DELETE CASCADE,
fundID INT REFERENCES fund(fundID) NOT NULL,
transDate DATE,
shares INT,
FOREIGN KEY (fundID) REFERENCES fund(fundID) ON UPDATE CASCADE ON DELETE CASCADE
);
Here’s my query:
select f.transdate, count (f.sin)
from (select t1.transdate, t1.sin, sum(t2.shares)
from fund f natural join trans t1 natural join trans t2
where f.fundname='Energy'
and t1.sin = t2.sin
and t2.transdate <= t1.transdate
group by t1.transdate, t1.sin
having sum(t2.shares) > 0)as f group by f.transdate
order by f.transdate;
This returns total customers holding shares on that day. However, I also want to add customers who were holding shares in the same fund all the days before.
So lets say, if I add the following inserts:
INSERT INTO trans VALUES (DEFAULT, '1', '3', '2011-10-10', 400);
INSERT INTO trans VALUES (DEFAULT, '3', '3', '2011-10-11', 324);
INSERT INTO trans VALUES (DEFAULT, '5', '3', '2011-10-17', 201);
INSERT INTO trans VALUES (DEFAULT, '8', '3', '2011-10-17', 472);
So the query I stated would return this:
transdate | count
------------+-------
2011-10-10 | 1
2011-10-11 | 1
2011-10-17 | 2
However, I would like it to be like this:
transdate | count
------------+-------
2011-10-10 | 1
2011-10-11 | 2
2011-10-17 | 4
As you can see, at the end of 2011-10-11, a total of 2 people were holding shares in that fund and so on.
Any help?
What you need is a windowing function, specifically using the “lag” function. I am not sure what version of PostgreSQL you have and when these windowing functions were first supported, but here is the documentation for the current 9.x series:
Windowing overview: http://www.postgresql.org/docs/9.0/interactive/tutorial-window.html
and:
Window functions: http://www.postgresql.org/docs/9.0/interactive/functions-window.html
There might be a rather efficient way of rewriting your query with this in mind but I do not have time to work on that. I can say that the easiest, even if not best, method of getting your intended result would be to take your current query, make it a CTE (http://www.postgresql.org/docs/9.0/interactive/queries-with.html) and use the windowing function in the query that uses the CTE. Meaning:
Something to that effect. Hope this helps :).