Reputation: 59
I'm very not SQL savvy at all but I've been tasked with putting together a report for CIS benchmark test scores. I need to get the most recent score for each system without duplicates.
The system_identifier table houses the system info fields; I'm grabbing the value type 1426 (hostname)
The test_result table contains the score and date fields.
Here is my current query:
SELECT system_identifier.value AS [System Name], test_result.score + '%' AS [Most Recent Score], LEFT(MAX(test_result.upload_date), 10) AS [Test Date]
FROM system_identifier INNER JOIN test_result ON system_identifier.target_system_id = test_result.target_system_id
WHERE (system_identifier.type_id = 1426)
GROUP BY system_identifier.value, test_result.score
ORDER BY system_identifier.value
This is currently returning all records where the System Name + Score combination is unique.
System Name Most Recent Score Test Date
----------- ----------------- ---------
system1 84 2019-06-10
system1 87 2019-08-24
system1 94 2019-09-14
system2 78 2019-07-22
system2 85 2019-09-12
system3 65 2019-05-23
system3 74 2019-07-03
system3 81 2019-08-09
system3 91 2019-09-10
Here is what I need:
System Name Most Recent Score Test Date
----------- ----------------- ---------
system1 94 2019-09-14
system2 85 2019-09-12
system3 91 2019-09-10
I've tried researching this but I'm not sure how to frame my question for a search, so I thought I'd ask here since I can be more verbose with what I'm looking for.
Let me know if you need any more info.
EDIT Neeraj's answer put me on the right track, so marking as the answer.
I ended up creating a view with the initial SELECT to put everything in one table called "merged." Then, I had success with this query (with some formatting to make it pretty):
SELECT DISTINCT
UPPER(merged.value) AS Hostname,
merged.score + '%' AS Score
LEFT(merged.upload_date,10) AS [Date Uploaded],
FROM dbo.merged
INNER JOIN (SELECT merged.value AS hostname, MAX(merged.upload_date) AS Uploaded
FROM dbo.merged
GROUP BY merged.value) t2
ON merged.value = t2.hostname
AND merged.upload_date = t2.Uploaded
WHERE merged.type_id = 1426
ORDER BY hostname
Upvotes: 1
Views: 96
Reputation: 1059
Use correlated subquery:
select t1.SystemName, t1.MostRecentScore, t1.TestDate
from myTable t1
where t1.TestDate =
(
select max(t2.TestDate)
from myTable t2
where t2.SystemName = t1.SystemName
)
Upvotes: 2
Reputation: 14928
You could also use a subquery as
WITH T AS
(
SELECT *
FROM
(
VALUES
('system1', 84, '2019-06-10'),
('system1', 87, '2019-08-24'),
('system1', 94, '2019-09-14'),
('system2', 78, '2019-07-22'),
('system2', 85, '2019-09-12'),
('system3', 65, '2019-05-23'),
('system3', 74, '2019-07-03'),
('system3', 81, '2019-08-09'),
('system3', 91, '2019-09-10')
) T(SystemName, MostRecentScore, TestDate)
)
SELECT T.*
FROM T INNER JOIN
(
SELECT SystemName,
MAX(TestDate) TestDate
FROM T
GROUP BY SystemName
) TT ON T.SystemName = TT.SystemName
AND
T.TestDate = TT.TestDate;
Upvotes: 0
Reputation: 222702
Use ROW_NUMBER()
:
SELECT System_Name,Most_Recent_Score,Test_Date
FROM (
SELECT
t.*,
ROW_NUMBER() OVER(PARTITION BY system_name ORDER BY test_date DESC) rn
FROM mytable t
) x WHERE rn = 1
In the inner query, ROW_NUMBER()
assigns a rank to each record within groups of records having the same system name, ordered by descending test date. Then the outer query selects the top record in each group.
System_Name | Most_Recent_Score | Test_Date :---------- | ----------------: | :------------------ system1 | 94 | 14/09/2019 00:00:00 system2 | 85 | 12/09/2019 00:00:00 system3 | 91 | 10/09/2019 00:00:00
Upvotes: 1