简体   繁体   中英

How to get records with top dates in SQL Server 2014?

I have an Account table and a StatementSummary table.

The StatementSummary table holds data for statements sent out every month for every account. But sometimes, for some reason, statements don't go out to the account holders.

I need a list of accounts where:

  1. The statement has not gone out for at least 6 months
  2. The Outstanding balance is at least $1000

My code:

SELECT A.AccountNumber
      ,StatementDate
      --,MAX(StatementDate)
      ,AmountDue
      ,InvoiceNumber


FROM [StatementSummary] S
INNER JOIN Account A ON S.AccountID = A.AccountId

WHERE AmountDue >= 1000
  AND StatementDate <= '2017-02-10'  --Should be (sysdate-180)

--GROUP BY A.AccountNumber, StatementDate

ORDER BY StatementDate DESC

This code gives me a list of accounts and their data for the statement period before 6 months ago. But these accounts have data for later statements as well.

I need accounts who have NOT received any statements since 6 months ago at least.



EDIT: ****
The only fields used from the Account Table are
1. AccountId
2) AccountNumber

The fields in the StatementSummary Table used are
1. AccountId
2. InvoiceNumber
3. StatementDate
4. NewCharges
5. AmountDue

A Statement is generated every month and every month, new charges are incurred on that account.

I need the details form the LAST Statement where:

1) the last StatementDate is before 6 months ago and
2) where the AmountDue is more at least $1000

Sample Data:

AccountNumber   StatementDate AmountDue InvoiceNumber
32563696        2017-07-16      1259.05 2279250276
32563696        2017-06-16      1043.00 2273976792
32563696        2017-05-16       974.00 2273976651
32067247        2017-07-01      5385.84 2277258801
32067247        2017-06-01      4218.71 2271971177
32067247        2017-05-01      2977.56 2276955130
32067247        2017-04-01      1518.85 2274063149
31279191        2017-06-01    214746.49 2271930486
31279191        2017-05-01    184178.38 2276913639
31279191        2017-04-01    141984.13 2274025518
31279191        2017-03-01    110914.52 2270228069
31279191        2017-02-01     76083.25 2257406893
31279191        2017-01-01     45997.75 2253462824

What I really need:

AccountNumber     StatementDate AmountDue     InvoiceNumber
11201057          2017-02-01    9114.29       2255223280
11201147          2017-02-01    1189.52       2255223235
11203824          2017-02-01    8984.36       2255223819
11206052          2017-01-01    2274.54       2255223381
11206298          2017-01-01    5792.11       2255223358
11208852          2016-12-01    2175.62       2255223987
11209202          2016-12-01    1199.58       2255223976
11209246          2016-12-01    1017.12       2255256003
11209268          2016-11-01    1775.32       2255256025


So, in plain words: I need a list of accounts and their data ONLY where the LAST statement sent for more than 6 months ago and also ONLY WHERE the AmountDue is $1000 or more.

I think this should do it, based off what you have posted. Though sample data would help.

WITH CTE AS(
    SELECT A.AccountNumber
          ,StatementDate
          --,MAX(StatementDate)
          ,AmountDue
          ,InvoiceNumber
          ,row_number() over (partition by A.AccountNumber order by StatementDate desc) as RN
    FROM [StatementSummary] S
    INNER JOIN Account A ON S.AccountID = A.AccountId
    WHERE
        s.AccountID in (select AccountID from StatementSummary group by AccountID having Max(StatementDate) < dateadd(day,-180,getdate()))
        and s.AmountDue >= 1000)

select
    AccountNumber
    ,StatementDate
    ,AmountDue
    ,InvoiceNumber
from CTE
where
    RN = 1

using not exists() :

SELECT A.AccountNumber
      ,S.StatementDate
      ,AmountDue
      ,InvoiceNumber
FROM [StatementSummary] S
INNER JOIN Account A ON S.AccountID = A.AccountId
WHERE AmountDue >= 1000
  and not exists (
    select 1 
    from [StatementSummary] i
    where i.AccountId = a.AccountId
      and i.StatementDate > dateadd(month,-6,getdate())
      /* other option based on comment */  
      and i.StatementDate > dateadd(day,-180,getdate())
    )
ORDER BY StatementDate DESC

inner join option to get the latest statement for an account when no statement has been sent within the last 6 months:

SELECT A.AccountNumber
      ,S.StatementDate
      ,AmountDue
      ,InvoiceNumber
FROM [StatementSummary] S
  INNER JOIN Account A 
    ON S.AccountID = A.AccountId
  inner join (
    select 
        AccountId
      , MaxStatementDate = max(StatementDate)
    from StatementSummary i
    group by i.AccountId
    having max(StatementDate) <= dateadd(month,-6,getdate())
    ) x on s.AccountId = x.AccountId 
       and s.StatementDate = x.MaxStatementDate
WHERE AmountDue >= 1000
ORDER BY StatementDate DESC
SELECT A.AccountNumber
      ,StatementDate
      --,MAX(StatementDate)
      ,AmountDue
      ,InvoiceNumber

FROM [StatementSummary] S
INNER JOIN Account A ON S.AccountID = A.AccountId

WHERE A.AmountDue >= 1000
  AND S.StatementDate <= '2017-02-10'

--Maybe both tables have same columns' name?

Use this query to get your 6 months case records:

Select * From [StatementSummary]
Where datediff(DAY, GETDATE(), StatementDate) Between -180 AND -1

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