I need to find the first and last price in a certain hour. Currently my query has a WHERE
clause that determines the hour I'm looking at.
Would there be a way of doing this so that I can just have show me the results for every hour for a particular date?
SELECT TOP 1 Price FROM MyData WHERE [Product] = 'XXXXXX' AND CAST([Deal] AS Date) = '2013-09-04' AND DATEPART(HOUR, [Deal]) = 9 Order By (datediff(minute, '1990-1-1', [Deal Time]) /60)
Deal
field is of type DateTime
AND DATEPART(HOUR, [Deal]) = 9
this is the bit I would like to replace with something that allows me to just see all entries where the price is the first price in that hour?
EDIT I'd like to be able to do it for any N minutes < an hour too? So like the end price after each half hour... etc..
You are trying to find the last price in each hour (as opposed to the maximum). You can do this. Let me start with your query so you can see the transformations (this is formatted so I can read it easily):
SELECT TOP 1 Price
FROM MyData
WHERE [Product] = 'XXXXXX' AND
CAST([Deal] AS Date) = '2013-09-04' AND
DATEPART(HOUR, [Deal]) = 9
Order By (datediff(minute, '1990-1-1', [Deal Time]) /60)
The idea is to assign a sequential number to each record within each hour. This number will start at the most recent time stamp and descend. Then, the latest price is the one where the sequential value is 1. This uses the window function row_number()
.
The resulting query doesn't use an explicit aggregation:
select DATEPART(HOUR, [Deal]), price
from (select md.*,
row_number() over (partition by DATEPART(HOUR, [Deal])
order by [Deal] desc) as seqnum
from MyData md
where [Product] = 'XXXXXX' AND
CAST([Deal] AS Date) = '2013-09-04'
) md
where seqnum = 1;
You can extend this to multiple days by removing the date condition from the where
clause to and adding a date value in the partition by
.