Reputation: 405
I am having trouble getting the 1 row with the latest date out of a multi-join statement.
3 tables involved:
(Unit)
SN | DateTime |
------------------|---------------------|
123 |2018-03-10 15:23:32 |
456 |2018-03-10 15:40:15 |
789 |2018-03-10 15:53:58 |
(History)
ID |SN |
-------|------------------|
84 |123 |
85 |456 |
86 |789 |
(Link)
SN | ID |
------------------|---------|
123 |84 |
456 |85 |
789 |86 |
(Station)
ID |Type | datetime |location |
-------|----------------|--------------------|-------------------------|
84 |ALPHA |2017-08-21 16:54:23 |X |
84 |BRAVO |2017-08-21 16:56:08 |X1 |
277 |DELTA |2017-08-21 17:46:11 |Y |
Goal
Get a joined table that will only show those rows with the most recent datetime per row and type selected.
I have managed to join up the tables, even sort the datetimes so that the most recent date is always the top 1, but I have no clue how then to select this top 1 I am interested in.
I have been at this now for several days no and cannot get only the one row that I need. I always end up with duplicates such as (Station) ID 84.
What I have tried before
SELECT rs.Unit, max(rf2.Type) as mydate, rf2.Type, rf2.ID
FROM DB.dbo.Unit rs
INNER JOIN DB.dbo.Link rf ON ( rs.ID = rf.ID )
INNER JOIN DB.dbo.History rf1 ON ( rf.SN = rf1.SN)
INNER JOIN DB.dbo.Station rf2 ON ( rf1.ID = rf2.ID )
where rf2.Type like 'AL%'
GROUP BY rs.SN, rf2.DateTime, rf2.Type, rf2.ID
order by rs.SN, rf2.DateTime desc;
I also tried a CTE, but same problem: I do not know how to only keep the most recent rows.
Result of above
SN |mydate |Type |ID |
------------------|---------------------|-------------|-------|
666 |2017-09-23 15:15:58 |Alpha |189 |
777 |2017-09-01 16:13:16 |Alpha7 |138 |
*123* |*2017-11-03 09:17:51*|*Alpha1* |*84* |
123 |2017-11-01 03:08:09 |Alpha2 |84 |
123 |2017-11-01 03:07:59 |Alpha3 |84 |
Basically what I would need is a table that only keeps unique rows such as the one marked with stars (123), most recent date, specific Type as in 'like 'AL%'.
After @Ferc's comment I tried something like this:
select ts.ID, ts.DateTime, ts.location
from (select ID, DateTime, location
row_number() over(partition by ID order by DateTime desc) as rn
from DB.dbo.Station where station like 'AL%') as ts
where rn = 1;
I got "SQL Error [102] [S0001]: Incorrect syntax near '('.
Incorrect syntax near '('.
Incorrect syntax near '('."
as an (complete rubbish) error message.
I then put a ',' after location and got a result.
I will try to incorporate this into my CTE.
Upvotes: 0
Views: 473
Reputation: 46249
If I understand correct you might do like this.
You need to write a subquery with ROW_NUMBER
with OVER(partition by rf2.ID,rs.SN order by rf2.[datetime] desc)
you will get the group number on rf2.ID
and rs.SN
.
Then getting the RowNumber = 1
row,which mean newest date.
SELECT t.SN,t.[datetime],t.Type,t.ID
FROM(
SELECT rs.SN,
rf2.[datetime],
rf2.[Type],
rf2.ID,
ROW_NUMBER() OVER(partition by rf2.ID,rs.SN order by rf2.[datetime] desc) rn
FROM Unit rs
INNER JOIN Link rf ON ( rs.SN = rf.SN )
INNER JOIN History rf1 ON ( rf.SN = rf1.SN)
INNER JOIN Station rf2 ON ( rf1.ID = rf2.ID )
WHERE rf2.Type like 'AL%'
) t
where t.rn = 1
sqlfiddle:http://sqlfiddle.com/#!18/36061/2
Upvotes: 0
Reputation: 3821
select * from (
select
row_number() over(partition by rf2.[datetime] order by rf2.[datetime] desc) as rn
,rf2.*
FROM Unit rs
INNER JOIN Link rf ON ( rs.SN = rf.SN )
INNER JOIN History rf1 ON ( rf.SN = rf1.SN)
INNER JOIN Station rf2 ON ( rf1.ID = rf2.ID )
where rf2.Type like 'AL%'
) T
where rn = 1;
Upvotes: 1