Say I have a table with the following information (sorted here for display purposes)
taskid | reference | centreid | date_out
---------------------------------------------------
10001 | 'IX#001323' | 1 | '2012-09-28'
10022 | 'IX#001323' | 2 | '2012-10-04'
10032 | 'IX#001544' | 1 | '2012-10-09'
10046 | 'IX#001666' | 1 | '2012-10-10'
10056 | 'IX#001666' | 3 | '2012-10-13'
10078 | 'IX#002100' | 2 | '2012-10-23'
10098 | 'IX#002100' | 1 | '2012-11-01'
I want to select the groups of rows that have the same reference where the first occurrence belonged to a particular centreid, but where the second occurrence was within a particular date range. For example, I want to find all taskids that have the same reference where the second date falls in October but the first centreid is 1, the results should be:
taskid | reference | centreid | date_out
---------------------------------------------------
10001 | 'IX#001323' | 1 | '2012-09-28'
10022 | 'IX#001323' | 2 | '2012-10-04'
10046 | 'IX#001666' | 1 | '2012-10-10'
10056 | 'IX#001666' | 3 | '2012-10-13'
It's possible that there are more than two taskids with the same reference, in which case, I am always interested in the last date and the second to last centreid (when ordered by date_out). Each time I write a query it ends up being very complex and still not returning exactly the rows I want.
I have:
SELECT taskid
FROM tasks t1
WHERE (EXISTS (SELECT 1
FROM tasks t2
WHERE t1.taskid <> t2.taskd
AND t1.reference = t2.reference))
AND
-- STUCK
-- Unsure how to select amongst remaining rows where max(date) between two dates
Thanks in advance for any help. I'm using PostgreSQL 9.1 if that makes any difference...
Update (2012-11-10)
I have used the answer provided by Erwin, but the self join in CTE d took a long time to execute, so I split it up into two different CTEs. This provided an overwhelming performance improvement. Erwin's original answer executed in around 120 seconds (choking on CTE d) whereas the below executes in just under 2 seconds.
... snip ...
,d AS (
SELECT reference, grp
FROM c
WHERE c.rn = 1 AND c.date_out BETWEEN '2012-10-01' AND '2012-10-31'
)
,e AS (
SELECT reference, grp
FROM c
WHERE c.rn = 2 AND centreid = 1
)
SELECT b.taskid, b.reference, b.centreid, b.date_out
FROM b
JOIN d USING (reference, grp)
JOIN e USING (reference, grp)
ORDER BY reference, date_out
