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?
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 .
Why don't you just check if they have a record where the password hasn't expired - eg, 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';
Edit: Sargability - change WHERE to use indexes
The above (and potentially in other answers) is a non-sargable query. It has to do the calculation for every row even if you have an index.
If we calculate the cutoff/criterion date instead, then just compare with the data directly, it allows use of indexes if you have them.
IF NOT EXISTS
(SELECT *
FROM PASSWORD_HISTORY CHP
WHERE CHP.CreationDate >= DATEADD(day, -90, CAST(getdate() AS date))
AND CHP.ClientId = 1
)
SELECT 'Password expired';
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
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.