Reputation: 1258
I have a requirement for an SQL Server 2005 query I need to write and it's stumping me how to accomplish it. I'll simplifiy it quite a bit, but the essence is that, if a client has no billings more recent than a certain date, I need to select up to 3 of that client's most recent billings. But if they have billings after that cutoff date, just display any of those billings.
So, if my cutoff date is Jan 1, 2010 and the data I have is as follows:
ClaimID ClientID BillingDate
1 1 March 12, 2010
2 1 June 3, 2010
3 1 January 5, 2008
4 1 February 9, 2011
5 1 May 19, 2005
6 2 November 20, 2005
7 2 October 5, 2009
8 3 January 4, 1999
9 3 July 8, 1997
10 3 May 7, 2010
11 3 August 6, 1999
12 4 May 25, 2000
13 4 April 1, 2005
14 4 March 9, 2009
15 4 December 5, 2007
16 4 December 19, 1998
17 4 June 3, 2006
Then I want to select:
ClaimID ClientID BillingDate
1 1 March 12, 2010
2 1 June 3, 2010
4 1 February 9, 2011
6 2 November 20, 2005
7 2 October 5, 2009
10 3 May 7, 2010
14 4 March 9, 2009
15 4 December 5, 2007
17 4 June 3, 2006
Anyone have any ideas? Thanks
Upvotes: 1
Views: 4124
Reputation: 77707
Rank the rows for every Client by descending BillingDate
.
For every client, output the dates that either:
are more recent than the cut-off date, or
belong to the 3 highest-ranked ones.
The query:
;WITH ranked AS (
SELECT
*,
rownum = ROW_NUMBER() OVER (PARTITION BY ClientID ORDER BY BillingDate DESC)
FROM Billings
)
SELECT ClaimID, ClientID, BillingDate
FROM ranked
WHERE BillingDate > @CutOffDate OR rownum BETWEEN 1 AND 3
Upvotes: 4
Reputation: 3447
Something like this should solve your problem? You can even make this a subselect if u want to
select ClaimID, ClientID, BillingDate
from bills
where BillingDate > @cutoffDate
UNION ALL
select ClaimID, ClientID, BillingDate
from bills a
where not exists (select 1 from bills b
where b.ClientId = a.ClientId
and b.BillingDate > @cutoffDate)
and 3 > (select count(1) from bills b
where b.ClientId = a.ClientId
and b.BillingDate>a.BillingDate)
Upvotes: 0
Reputation: 19339
You could use UNION ALL
to combine the results of two queries:
SELECT *
FROM MyTable
WHERE BillingDate > '1-Jan-2010'
UNION ALL
SELECT *
FROM MyTable T1
WHERE NOT EXISTS (SELECT *
FROM MyTable T2
WHERE T1.ClientID = T2.ClientID AND T2.BillingDate > '1-Jan-2010')
AND ClaimID IN (SELECT TOP 3 T3.ClaimID
FROM MyTable T3
WHERE T1.ClientID = T3.ClientID
ORDER BY T3.BillingDate DESC)
Upvotes: 1