I have the below table:
PasswordHistoryId ClientId Password CreationDate (dd/MM/YYYY)
1 1 abcd 05/01/2023
2 1 xyz 11/08/2022
3 2 efg 11/12/2022
I want to check if the latest password set has been expired. A password is considered as expired if it has been created more than 90 days ago.
I have the below SQL to check if a password has expired:
SELECT TOP 1 1 -- Returns 1 if password has expired
FROM PASSWORD_HISTORY CHP
WHERE (DATEDIFF(DAY, CHP.CreationDate, GETDATE())) > 90
AND CHP.ClientId = 1
ORDER BY CHP.CreationDate DESC
However this returns me 1 because of the second line in the table where the password was set on the 11th of August 2022 and it has already been expired. I need to do the comparison on the latest record based on the creation date.
Any idea of how I can do this?
CodePudding user response:
Use aggregation:
SELECT CASE
WHEN DATEDIFF(DAY, MAX(CreationDate), GETDATE()) > 90 THEN 1
ELSE 0
END AS expired
FROM PASSWORD_HISTORY
WHERE ClientId = 1;
See the demo.
CodePudding user response:
Why don't you just check if they have a record where the password hasn't expired - e.g., if they have a password less than or equal to 90 days, then don't flag them.
No sorting or other functions required.
IF NOT EXISTS
(SELECT *
FROM PASSWORD_HISTORY CHP
WHERE (DATEDIFF(DAY, CHP.CreationDate, GETDATE())) <= 90
AND CHP.ClientId = 1
)
SELECT 'Password expired';
CodePudding user response:
Just move DATEDIFF check to SELECT statement instead of WHERE:
SELECT TOP 1 CASE WHEN (DATEDIFF(DAY, CHP.CreationDate, GETDATE())) > 90 THEN 1 END
FROM PASSWORD_HISTORY CHP
WHERE CHP.ClientId = 1
ORDER BY CHP.CreationDate DESC
This will return NULL, though, if password is not expired. If you want to return nothing, you do need to use CTE or sub-query:
WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY CHP.CreationDate DESC) RN
FROM PASSWORD_HISTORY CHP
WHERE CHP.ClientId = 1
)
SELECT 1
FROM CTE
WHERE RN = 1
AND (DATEDIFF(DAY, CreationDate, GETDATE())) > 90