Reputation: 907
I have a database with a table for Engines (EngineId, Make, Model, SerialNumber, etc.) and a table with Test values on the engines (TestId, EngineId, Value1, Value2, etc).
I want to select all the records from the Engines table along with the latest test values (there may be mutliple test records but I only want the latest). It seems simple but for some reason I can't quite get the SQL syntax.
I can get started with something like the following but then I'm stuck.
SELECT e.*, t.Value1, t.Value2
FROM Engine e
left join Event ev on e.EngineID = ev.EngineID
left join Test t on ev.EventID = t.EventID
WHERE ev.EventType = 'TEST'
I can get close with the following but it only returns records with test data. I want to return engine records without test data:
SELECT e.*, t.Nox, t.CO
FROM Engine e
left join Event ev on e.EngineID = ev.EngineID
left join Test t on ev.EventID = t.EventID
left join EventType et on ev.EventTypeId = et.EventTypeID
WHERE Upper(et.Name) = 'TEST'
AND ev.EventDate= ( SELECT MAX(EventDate)
FROM Event ev2
left join EventType et2 on ev2.EventTypeID = et2.EventTypeID
WHERE ev2.EngineID = e.EngineID AND
Upper(et2.Name) = 'TEST')
I can get close with the following but I still need to join to Test table somehow:
SELECT DISTINCT e.*, om.maxdate
FROM Engine e
LEFT JOIN (
select ev2.EngineID, max(EventDate) as maxdate
from Event ev2
LEFT JOIN EventType et on ev2.EventTypeID = et.EventTypeID
WHERE Upper(et.Name) = 'TEST'
group by EngineID
) om on e.EngineID = om.EngineID
--LEFT JOIN Test t on om.EventID = t.EventID
I can do a stored procedure if that helps.
You asked for some sample data so here goes. I want to return all the engine records and along with that the latest test values.
Engine
EngineId Make Model SerialNumber
1 Waukesha 5794 C-62124
2 Waukesha 5800 F-199374
3 NULL NULL B-200305
4 Waukesha 6000 D-999777
5 Waukesha 6100 E-877324
6 Briggs & Stratton LW300 SL-122375
7 Briggs & Stratton LW350 SL-375200
8 Briggs & Stratton GS250 LS-988755
9 Briggs & Stratton 5794 SN12345
Test
TestID EventID EngineID TestDate Description Value1 Value2
1 7 1 03/01/17 12:00 AM Testing 30 50
9 8 1 01/01/17 12:00 AM Testing 20 20
17 11 1 12/01/16 12:00 AM Testing 16 15
Upvotes: 2
Views: 90
Reputation: 4066
You can use rank()
function to get only the last test per engine.
;with Tcte as (
SELECT e.*
, t.Value1
, t.Value2
, rank() over (partition by e.EngineID order by t.TestDate desc) r
FROM Engine e
left join Event ev on e.EngineID = ev.EngineID
left join Test t on ev.EventID = t.EventID WHERE ev.EventType = 'TEST')
SELECT * FROM Tcte WHERE r=1
Upvotes: 0
Reputation: 966
Try this
;with testValues as
( select ev.EngineID, ev.EventId ,t.TestId,t.Value1, t.Value2
,row_number() over(partition by ev.EventId order by ev.EventDate desc)rowNumber
from Event ev
left join Test t on ev.EventID = t.EventID
WHERE ev.EventType = 'TEST'
)
SELECT e.*, v.Value1, v.Value2
FROM Engine e
left join testValues v on e.EngineID = v.EngineID and v.rowNumber=1
Or this
;with testData as
(
SELECT e.*, t.Value1, t.Value2
,row_number() over(partition by ev.EventId order by ev.EventDate desc)rowNumber
FROM Engine e
left join Event ev on e.EngineID = ev.EngineID and ev.EventType = 'TEST'
left join Test t on ev.EventID = t.EventID
)
select * from testData where rowNumber=1
Upvotes: 0
Reputation: 12194
If you mean latest TEST event (based on EventDate) for given engine, then it is:
SELECT e.*, t.Value1, t.Value2
FROM Engine e
LEFT JOIN Event ev
ON e.EngineID = ev.EngineID
AND ev.EventType = 'TEST'
AND ev.EventDate = (SELECT MAX(ev2.EventDate)
FROM Event ev2
WHERE ev2.EngineID = e.EngineID
AND ev2.EventType = 'TEST')
LEFT JOIN Test t
ON ev.EventID = t.EventID
Please note that if the latest event has more test records, all of them will be returned, because all of them share the same latest EventDate. But this seems to be correct because you did not made distinction between multiple Test records assigned to the same Event, so they are equal.
Upvotes: 0
Reputation: 56934
When you say that you want the latest test-values, that implies that you'll have some kind of way of identifying the latest test-values. This can be done by retrieving the latest eventdate.
You will have to use a subquery with the query.
SELECT e.*, t.Value1, t.Value2
FROM Engine e
left join Event ev on e.EngineID = ev.EngineID
left join Test t on ev.EventID = t.EventID
WHERE ev.EventType = 'TEST'
AND ev.EventDate= ( SELECT MAX(EventDate)
FROM Event
WHERE Event.EventID = t.EventId
AND Event.EngineID = ev.EngineId )
This should give you the latest test-results for an event on an engine
Upvotes: 0
Reputation: 412
you can use the
SELECT TOP 1 e. *,t.Value1,t.Value2
to get the top record and to make sure the top is the latest, order the table with
ORDER BY column1, column2, ... ASC|DESC
Hope this helps....
Upvotes: 1