Reputation: 13
The table dbo.AllApps
logs all executable that has been run it has a column named ApplicationHash
which stores the exe hash value.
So if the exe has been run 10 times, there will be 10 entries in table with the same information but different timestamp.
I would like to produce a report that will only return 1 row from the 10 (with all columns time,name,desc ...) and one additional column that will provide the count of the number of times the exe has been executed.
Any suggestions?
`/* !!!!!DEFINE START AND END DATE FOR REPORT HERE!!!!!*/
DECLARE @StartDate DATETIME = 2017-01-01
DECLARE @EndDate DATETIME = 2017-01-02`
`/* Checks if the temp table #PCount exist and deletes the table if it does */
IF OBJECT_ID('tempdb..#PCount') IS NOT NULL
BEGIN
DROP TABLE #PCount
END`
`/* Performs a COUNT on the ApplicationHash entries */
SELECT ApplicationHash, COUNT(ApplicationHash) AS ProcessCount
INTO #PCount
FROM dbo.AllApps
WHERE
TokenType = 'Elevated'
AND ApplicationType != 'COM Class'
AND ApplicationType != 'ActiveX Control'
AND ProcessStartTime >= @StartDate
AND ProcessStartTime < @EndDAte
GROUP BY ApplicationHash`
`/* Pulls up the actual report and inserts the count value for the ApplicationHash */
SELECT #PCount.ProcessCount,
dbo.AllApps.ApplicationHash,
dbo.AllApps.ProcessStartTime,
dbo.AllApps.ApplicationType,
dbo.AllApps.Description,
dbo.AllApps.Publisher,
dbo.AllApps.ProductName,
dbo.AllApps.ProductVersion,
dbo.AllApps.EventDescription,
dbo.AllApps.CommandLine,
dbo.AllApps.FileName
FROM #PCount, dbo.AllApps
WHERE dbo.AllApps.ApplicationHash = #PCount.ApplicationHash
AND TokenType = 'Elevated'
AND ApplicationType != 'COM Class'
AND ApplicationType != 'ActiveX Control'
AND ProcessStartTime >= @StartDate
AND ProcessStartTime < @EndDate
ORDER BY ProcessStartTime DESC`
Upvotes: 1
Views: 178
Reputation: 82534
The easy way is to use a cte and row_number:
;with cte as
(
SELECT ROW_NUMBER() OVER(PARTITION BY ApplicationHash ORDER BY ProcessStartTime) as rn,
#PCount.ProcessCount,
dbo.AllApps.ApplicationHash,
dbo.AllApps.ProcessStartTime,
dbo.AllApps.ApplicationType,
dbo.AllApps.Description,
dbo.AllApps.Publisher,
dbo.AllApps.ProductName,
dbo.AllApps.ProductVersion,
dbo.AllApps.EventDescription,
dbo.AllApps.CommandLine,
dbo.AllApps.FileName
FROM #PCount
INNER JOIN dbo.AllApps ON dbo.AllApps.ApplicationHash = #PCount.ApplicationHash
WHERE TokenType = 'Elevated'
AND ApplicationType != 'COM Class'
AND ApplicationType != 'ActiveX Control'
AND ProcessStartTime >= @StartDate
AND ProcessStartTime < @EndDate
)
SELECT ProcessCount,
ApplicationHash,
ProcessStartTime,
ApplicationType,
Description,
Publisher,
ProductName,
ProductVersion,
EventDescription,
CommandLine,
FileName
FROM CTE
WHERE rn = 1
Please note I've changed your implicit join to an explicit join.
Read Aaron Bertrand's Bad habits to kick : using old-style JOINs to find out why.
Upvotes: 1
Reputation: 38073
Using top with ties
with row_number()
to get the row with the most recent ProccessStartTime
and count(*) over()
for the ProcessCount
.
Note: the temporary table is not needed for this solution. If the where
criteria were not the same for both queries, then it would be a different story.
Update: Without knowing more about the data types and the presence of a unique id for rows on this table, I have added a case
expression to include the ProcessStartTime
to the partition when ApplicationHash
= <None>
, else a constant (@StartDate
).
declare @StartDate datetime = '20170101';
declare @EndDate datetime = '20170102';
select top 1 with ties
ProcessCount = count(*) over (
partition by ApplicationHash
, case
when ApplicationHash = '<None>'
then ProcessStartTime
else @StartDate
end
order by ProcessStartTime desc
)
, ApplicationHash
, ProcessStartTime
, ApplicationType
, Description
, Publisher
, ProductName
, ProductVersion
, EventDescription
, CommandLine
, FileName
from dbo.AllApps aa
where TokenType = 'Elevated'
and ApplicationType != 'com Class'
and ApplicationType != 'ActiveX Control'
and ProcessStartTime >= @StartDate
and ProcessStartTime < @EndDate
order by row_number() over (
partition by ApplicationHash
, case
when ApplicationHash = '<None>'
then ProcessStartTime
else @StartDate
end
order by ProcessStartTime desc
)
Upvotes: 0