Reputation: 149
I have a table (SPG) with person (DonorID), dates of Donation (DonateDate) and place of Donation (Center). I would like to find the date & place of a donation (easy), then the date and place of the next donation, with the gap between the two dates.
I have used a SELECT subquery which gives me the next date (NextDate) but I can't then get the matching Center:
SELECT SPG.DonorID,
SPG.DonateDate,
SPG.Center AS Center1,
(SELECT Min(DonateDate) as MinDate
FROM SPG As A
WHERE SPG.DonorID = A.DonorID
AND A.DonateDate > SPG.DonateDate) AS NextDate,
[NextDate]-[DonateDate] AS Gap
FROM SPG
GROUP BY SPG.DonorID, SPG.DonateDate, SPG.Center
HAVING ((((SELECT Min(DonateDate) as MinDate
FROM SPG As A
WHERE SPG.DonorID = A.DonorID
AND A.DonateDate > SPG.DonateDate))<>""))
ORDER BY SPG.DonorID, SPG.DonateDate;
I have a different INNER JOIN query which gives me the Center but it returns all future donations, not just the next one:
SELECT A.DonorID,
A.DonateDate,
A.Center,
Min(B.DonateDate) AS NextDate,
B.Center,
[B].[DonateDate]-[A].[DonateDate] AS Gap
FROM SPG AS A INNER JOIN SPG AS B ON A.DonorID = B.DonorID
WHERE B.DonateDate > A.DonateDate
GROUP BY A.DonorID,
A.DonateDate,
A.Center,
B.Center,
B.DonateDate-A.DonateDate;
Basically, I can't seem to combine the Min() command from the sub-query with returning more than field from a JOIN.
(Please excuse the different notation - lots of copying & pasting of trial code)
Upvotes: 0
Views: 227
Reputation: 16025
One of the SQL gods here may know of a cleaner way, but this is all I have at present:
select
s1.donorid,
s1.donatedate,
s1.center as center1,
(
select min(s2.donatedate)
from spg s2
where s1.donatedate < s2.donatedate and s1.donorid = s2.donorid
) as nextdate,
(
select s2.center
from spg s2
where
s1.donorid = s2.donorid and
s2.donatedate =
(
select min(s3.donatedate)
from spg s3
where s1.donatedate < s3.donatedate and s1.donorid = s3.donorid
)
) as center2,
nextdate - s1.donatedate as gap
from
spg s1
order by
s1.donorid,
s1.donatedate
And if you're only after those records which have a 'next' donation date, perhaps:
select
s1.donorid,
s1.donatedate,
s1.center as center1,
(
select min(s2.donatedate)
from spg s2
where s1.donatedate < s2.donatedate and s1.donorid = s2.donorid
) as nextdate,
(
select s2.center
from spg s2
where
s1.donorid = s2.donorid and
s2.donatedate =
(
select min(s3.donatedate)
from spg s3
where s1.donatedate < s3.donatedate and s1.donorid = s3.donorid
)
) as center2,
nextdate - s1.donatedate as gap
from
spg s1
where exists
(select 1 from spg s2 where s1.donorid = s2.donorid and s1.donatedate < s2.donatedate)
order by
s1.donorid,
s1.donatedate
I heard you like correlated subqueries...
Upvotes: 2