SQL group by - How to get new records that did not exist in any previous month

Viewed 48

I have the following data.

DECLARE @Table TABLE(
RequestID varchar(100)
, PersonID varchar(100)
, StartDate DATE
, EndDate DATE
, StatusType VARCHAR(150)
)

INSERT INTO @Table
SELECT '445566', 'Person2', '9/13/2022', '9/16/2022', 'TransactionStarted'
UNION ALL
SELECT '445566', 'Person2', '9/13/2022', '9/16/2022', 'TransactionEnded'
UNION ALL
SELECT '112233', 'Person2', '8/13/2022', '8/16/2022', 'TransactionStarted'
UNION ALL
SELECT '112233', 'Person2', '8/13/2022', '8/16/2022', 'TransactionEnded'
UNION ALL
SELECT '556677', 'Person1', '8/10/2022', '8/12/2022', 'TransactionStarted'
UNION ALL
SELECT '556677', 'Person1', '8/10/2022', '8/12/2022', 'TransactionEnded' 

I get the data out like this, and it works well

SELECT COUNT(Distinct RequestID) TotalCountPerPerson,  DATENAME(mm, StartDate) [SRMonthName], MONTH(StartDate) [SRMonthNumber], YEAR(StartDate) [SRYear]
FROM @Table
GROUP BY  MONTH(StartDate), DATENAME(mm,StartDate), YEAR(StartDate)
ORDER BY  YEAR(StartDate), MONTH(StartDate)

But, I need an additional point of data that I am having trouble figuring out how to get. In the sample data, You can see that "Person 2" and "Person1" were both "new" to the system in August. I need a way to add them to the query so that I can get Total Count and New Count per month and year. Anyone help with the query?

SELECT 2 TotalCountPerPerson, 2 NewThisMonth,   'August'[SRMonthName],  8 [SRMonthNumber],  2022 [SRYear]
UNION ALL
SELECT 1, 0 NewThisMonth,'September',   9,  2022
1 Answers

You may use a self left join as the following:

SELECT COUNT(Distinct T.PersonID) TotalCountPerPerson, 
       COUNT(Distinct CASE WHEN D.PersonID IS NULL THEN T.PersonID END) NewThisMonth,
       DATENAME(mm, T.StartDate) [SRMonthName], 
       MONTH(T.StartDate) [SRMonthNumber], YEAR(T.StartDate) [SRYear]
FROM @Table T LEFT JOIN @Table D
ON T.PersonID = D.personID AND T.StartDate > D.StartDate
GROUP BY MONTH(T.StartDate), DATENAME(mm,T.StartDate), YEAR(T.StartDate)
ORDER BY YEAR(T.StartDate), MONTH(T.StartDate)

Also, you may use EXISTS operator as the following:

WITH CTE AS
  (
    SELECT *, CASE WHEN NOT EXISTS
                   (SELECT 1 FROM @Table D WHERE D.PersonID = T.PersonID AND D.StartDate<T.StartDate) 
                   THEN T.PersonID
              END AS ISNEW
    FROM @Table T 
  )
SELECT COUNT(Distinct PersonID) TotalCountPerPerson, 
       COUNT(Distinct ISNEW) NewThisMonth,
       DATENAME(mm, StartDate) [SRMonthName], 
       MONTH(StartDate) [SRMonthNumber], YEAR(StartDate) [SRYear]
FROM CTE
GROUP BY MONTH(StartDate), DATENAME(mm,StartDate), YEAR(StartDate)
ORDER BY YEAR(StartDate), MONTH(StartDate);

See a demo.

Related