Actual situation
A change request (field „pcr“) only can have one unique assigned user that shall be informed about the assignment every night.
The assigned user (field „created_by“) of a change requests (field „pcr“) is changing several times a day. Every time the user (field „created_by“) changes to another user, a table entry with the actual time stamp (field „created_on“) is inserted to a SQL table.
At the end of the day, the system shall report via email the users that have been assigned to a PCR (only one user per change request).
The following table contains entries with people wo shall be informed every evening.
id | pcr | created_on | created_by |
---|---|---|---|
1 | PCR-1 | 2020-02-26 09:20:52.977 | user1 |
2 | PCR-1 | 2020-02-26 09:20:54.667 | user1 |
3 | PCR-2 | 2020-02-26 09:20:57.137 | user1 |
4 | PCR-2 | 2020-02-26 09:20:59.003 | user1 |
5 | PCR-2 | 2020-02-26 09:21:07.540 | user3 |
6 | PCR-3 | 2020-02-26 09:21:09.850 | user3 |
7 | PCR-4 | 2020-02-26 09:21:12.850 | user3 |
8 | PCR-4 | 2020-02-26 09:21:15.100 | user3 |
9 | PCR-5 | 2020-02-26 09:21:55.323 | user3 |
10 | PCR-2 | 2020-02-26 09:22:06.037 | user2 |
11 | PCR-5 | 2020-02-26 09:22:07.037 | user2 |
12 | PCR-7 | 2020-02-26 09:22:08.760 | user2 |
13 | PCR-7 | 2020-02-26 10:20:07.233 | user2 |
14 | PCR-8 | 2020-02-26 10:20:08.967 | user2 |
15 | PCR-8 | 2020-02-26 10:20:13.393 | user1 |
16 | PCR-9 | 2020-02-26 10:20:15.020 | user1 |
17 | PCR-7 | 2020-02-26 10:20:19.497 | user3 |
18 | PCR-9 | 2020-02-26 10:20:20.163 | user3 |
A nightly executed batch job (at 23:59h every evening) shall provide the possibility to inform user1, user2 or user3 about their assigned PCR’s. Only the latest entry per PCR, that can be recognized by the timestamp (field „created_on“) represent the user assigned user at the end of the day
Problem
The SQL Statement shall output the latest entry per assigned user of each PCR. With a standard aggregate function this is not possible because the whole row entry has to be retrieved.
Approach
The Microsoft SQL Server has a proprietary function RANK(), that prints out the ranking of the PCR entry in connection with PARTITION BY and ORDER BY. The ORDER BY has to be used DESC, so that the latest entry always is on rank 1.
Because this methods only can be used within the SELECT statements fields and not withing WHERE, we need a second parent query to select everything with rank 1.
Solution
SELECT *
FROM (
SELECT id,
pcr,
created_on,
created_by,
RANK () OVER (
PARTITION BY pcr
ORDER BY created_on DESC
) as biggestHasRangOne
FROM nightly_email
)tab
WHERE biggestHasRangOne=1
AND CONVERT(date, GETDATE())=CONVERT (date, created_on)
To get the smallest one (minimum) in for that day you have to use
ORDER BY created_on ASC
In the RANK() – Partition by -Syntax.