Reputation: 13
I'm trying to identify if the value of a column (let's call it status for now) is appearing for the first time for a given ID, or if it's previously held that value before. If its the first time that the status is equal to 1 or 2, I'd like to return a 1=Y or a 0=N. The results below are what I'm looking to recreate. Any help is greatly appreciated. Thanks
ID Date Status First Time
1 1/1/2017 1 Y
2 1/1/2017 0 N
3 1/1/2017 0 N
4 1/1/2017 2 Y
5 1/1/2017 0 N
1 2/1/2017 0 N
2 2/1/2017 0 N
3 2/1/2017 1 Y
4 2/1/2017 0 N
5 2/1/2017 1 Y
1 3/1/2017 2 N
2 3/1/2017 0 N
3 3/1/2017 0 N
4 3/1/2017 1 N
5 3/1/2017 1 N
Upvotes: 0
Views: 3260
Reputation: 15961
SELECT t1.ID, t1.Date, t1.status
, CASE WHEN firsts.ID IS NULL THEN 'N' ELSE 'Y' END AS `First Time`
FROM theTable AS t1
LEFT JOIN
(SELECT ID, MIN(Date) AS fDate
FROM theTable AS t0
WHERE status IN (1, 2)
GROUP BY ID
) AS firsts
ON t1.ID = firsts.ID AND t1.status IN (1, 2) AND t1.Date = firsts.fDate
;
You can use a subquery to identify the firsts, and join to the original records to "add" that information.
Note: This could lead to some redundant firsts if an ID's first 1 and 2 status values occur on the same day; but the current definition of "first" does't really state which status would be "first".
Upvotes: 1
Reputation: 1077
Working solution, if I understand the problem correctly:
Test Table Creation:
WITH Test (ID, [Date], [Status]) AS (
SELECT * FROM (
VALUES
(1,Convert(datetime, '1/1/2017', 120),1),
(2,Convert(datetime, '1/1/2017', 120),0),
(3,Convert(datetime, '1/1/2017', 120),0),
(4,Convert(datetime, '1/1/2017', 120),2),
(5,Convert(datetime, '1/1/2017', 120),0),
(1,Convert(datetime, '2/1/2017', 120),0),
(2,Convert(datetime, '2/1/2017', 120),0),
(3,Convert(datetime, '2/1/2017', 120),1),
(4,Convert(datetime, '2/1/2017', 120),0),
(5,Convert(datetime, '2/1/2017', 120),1),
(1,Convert(datetime, '3/1/2017', 120),2),
(2,Convert(datetime, '3/1/2017', 120),0),
(3,Convert(datetime, '3/1/2017', 120),0),
(4,Convert(datetime, '3/1/2017', 120),1),
(5,Convert(datetime, '3/1/2017', 120),1)
) AS A (Column1, Column2, Column3)
)
Query:
SELECT id,
[Date],
(SELECT [Status] FROM Test b
WHERE a.ID = b.ID
AND a.[Date] = b.[Date]) AS [Status],
CASE WHEN (SELECT MIN([Date])
FROM Test
WHERE [Status] IN (1, 2)
AND ID = a.ID
GROUP BY ID
) = a.[Date] THEN 'Y'
ELSE 'N'
END AS FirstTime
FROM Test a
GROUP BY ID, [Date]
Upvotes: 0
Reputation: 3665
Something like this may work for you. The ROW_NUMBER function ordered by date and partitioned by status will add a counter that, within each group of similar statuses, will increment from 1 according to ascending date.
Combining this with a CASE statement, we can say that the status a 'first time' when that counter is either a 1 or two.
SELECT
*
, CASE WHEN ROW_NUMBER() OVER (PARTITION BY [Status] ORDER BY [date]) IN (1,2) THEN 'Y' ELSE 'N' END
FROM [MY_TABLE]
EDIT: As noted below, this is a SQL Sever solution. You would make some tweaks to get it in MYSQL.
Upvotes: 0
Reputation: 2896
Just check if Status is 1 or 2, and whether there exists a record with the same ID and at an earlier date with Status 1 or 2.
select ID, Date, Status,
case
when a.Status in (1,2) and not exists(select * from table b where a.ID = b.ID and b.Status in (1,2) and b.Date < a.Date) then 'Y'
else 'N'
end as First
from table a
Upvotes: 0