Reputation: 3272
I have a table like the below sample. I'm trying to get the row of every user having status 0 and if there is a duplicate UserId then get the row with max(CreatedDate) for that user
TableA
+----+--------+-------------+--------+
| Id | UserId | CreatedDate | Status |
+----+--------+-------------+--------+
| 1 | a234 | 09/02/2017 | 0 |
| 2 | a234 | 09/03/2017 | 0 |
| 3 | a234 | 09/06/2017 | 1 |
| 4 | a143 | 08/25/2017 | 0 |
+----+--------+-------------+--------+
Expected Output
+----+--------+-------------+--------+
| Id | UserId | CreatedDate | Status |
+----+--------+-------------+--------+
| 2 | a234 | 09/03/2017 | 0 |
| 4 | a143 | 08/25/2017 | 0 |
+----+--------+-------------+--------+
SQL Query
SELECT d.Id, d.UserId,d.CreatedDate,d.Status FROM
(
SELECT Id, Max(CreatedDate) as MaxDate
FROM TableA
GROUP BY Id
HAVING Count(*)>1
) r
INNER JOIN TableA d
ON d.Id=r.Id AND d.CreatedDate=r.MaxDate AND Status=0
But I think the condition is wrong which should be like a sequence eg:
1st condition Status=0
2nd Condition If Duplicate UserId exist take Max(CreatedDate) else CreatedDate
Upvotes: 1
Views: 14061
Reputation: 10701
There is a solution using subquery in WHERE
SELECT d.Id, d.UserId, d.CreatedDate,d.Status
FROM TableA d
WHERE d.Status = 0 and d.CreatedDate =
(
SELECT MAX(x.CreatedDate)
FROM TableA x
WHERE x.Status = 0 AND x.UserId = d.UserId
)
another solution might be using NOT EXISTS
SELECT d.Id, d.UserId, d.CreatedDate,d.Status
FROM TableA d
WHERE d.Status = 0 and NOT EXISTS
(
SELECT MAX(x.CreatedDate)
FROM TableA x
WHERE x.Status = 0 AND x.UserId = d.UserId AND
x.CreatedDate > d.CreatedDate
)
or ALL
SELECT d.Id, d.UserId, d.CreatedDate,d.Status
FROM TableA d
WHERE d.Status = 0 and d.CreatedDate >=
ALL(
SELECT x.CreatedDate
FROM TableA x
WHERE x.Status = 0 AND x.UserId = d.UserId
)
Upvotes: 1
Reputation: 1612
I believe you will find the below SQL to be more efficient and elegant.
SELECT Id, UserId, CreatedDate, Status,
MAX (CreatedDate) OVER (PARTITION BY USerId) AS max_CreatedDate
FROM TableA
WHERE Status = 0;
Let me know if it works OK for you!
Ted.
Upvotes: 0
Reputation: 3606
Try this:-
SELECT d.Id, d.UserId,d.CreatedDate,d.Status FROM
(
SELECT UserId, Max(CreatedDate) as MaxDate
FROM TableA
WHERE Status = 0
GROUP BY UserId
) r
INNER JOIN TableA d
ON d.UserId=r.UserId AND d.CreatedDate=r.MaxDate AND Status=0
Your GROUP BY
and JOIN
needed to be on UserId
for this to work, and I've moved the filter by Status=0
to the derived table / subquery.
Upvotes: 4
Reputation: 27
select
ID
, UserID
, CreatedDate
, [Status]
from TableA A
inner join (
select
max(CreatedDated) [MaxDate]
, UserID
, [Status]
from TableA
where [Status] = 0
group by UserID, [Status]
) B on A.UserID = B.UserID and A.CreatedDate = B.MaxDate and A.[Status] = B.[Status]
I think the reason you were getting results that you didn't expect was your "having count(*) > 1" would only return duplicates.
Upvotes: 1