简体   繁体   中英

SQL: Select all rows that meet a condition if that condition is met, but only a certain nuber rows if it isn't

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

  1. Rank the rows for every Client by descending BillingDate .

  2. 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

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)

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM