views:

113

answers:

4

I need to write a SQL-Server query but I don't know how to solve. I have a table RealtimeData with data:

 Time                   |    Value
4/29/2009 12:00:00 AM   |   3672.0000
4/29/2009 12:01:00 AM   |   3645.0000
4/29/2009 12:02:00 AM   |   3677.0000
4/29/2009 12:03:00 AM   |   3634.0000
4/29/2009 12:04:00 AM   |   3676.0000      // is EOD of day "4/29/2009"
4/30/2009 12:00:00 AM   |   3671.0000
4/30/2009 12:01:00 AM   |   3643.0000
4/30/2009 12:02:00 AM   |   3672.0000
4/30/2009 12:03:00 AM   |   3634.0000
4/30/2009 12:04:00 AM   |   3632.0000
4/30/2009 12:05:00 AM   |   3672.0000      // is EOD of day "4/30/2009"
5/1/2009 12:00:00 AM    |   3673.0000
5/1/2009 12:01:00 AM    |   3642.0000
5/1/2009 12:02:00 AM    |   3672.0000
5/1/2009 12:03:00 AM    |   3634.0000
5/1/2009 12:04:00 AM    |   3635.0000      // is EOD of day "5/1/2009"

I want to get the EOD's data of days which exist in table. (EOD = end of day). With the my sample's data, I will need to reture a table like following:

   Time      |    Value
4/29/2009    |  3676.0000
4/30/2009    |  3672.0000
5/1/2009     |  3635.0000

Note: I write the comment so that you can know where is EOD. And SQL Server is version 2005.

Note: the data in RealtimeData table is very large with more than 400.000 rows. Please help me to write in optimization.

Please help me to solve my problem. Thanks.

+3  A: 
WITH RankedRealTimeData AS (
  SELECT *, ROW_NUMBER() OVER (
      PARTITION BY CONVERT(VARCHAR(10), [TIME], 121) 
      ORDER BY Time DESC) AS RN
  FROM RealTimeData
)
SELECT * FROM RankedRealTimeData WHERE RN=1;
Bill Karwin
Shouldn't that be `DATEPART(DAYOFYEAR, Time)`?
ongle
Don't you need another argument for the DATEPART function?
RBarryYoung
The query returns the correct result if you make the change to the `DATEPART` function as indicated above.
ongle
My bad. I have edited the function above.
Bill Karwin
This will not differentiate between records from different years. You could partition by CONVERT(VARCHAR(10), [TIME], 121) instead of DATEPART
Chris Bednarski
@Knoodles: thanks, done. This is a team effort!
Bill Karwin
@Chris good point. I wonder what gives better performance, casting it as a `VARCHAR` or having multiple `PARTITION BY` criteria (`DATEPART` year, `DATEPART` dayofyear)
ongle
@ongle: Both methods defeat the possibility of using an index, which I would guess (without having measured, admittedly) is a much greater performance penalty than the difference between two ways of extracting the components of the date. So if performance is a priority, I would do as you suggest in your comment to the OP question above, store components of the date separately, and index them.
Bill Karwin
@Bill Karwin, rather than splitting up the real date/time field into two fields which would change how the rest of the application interacts with this table the OP can create a persisted calculated field on the table which is just the date portion and then he can create an index on that persisted calculated field.
Sam
@Sam: Good point, I overlook the feature of calculated fields (and expression indexes) since I most often use MySQL.
Bill Karwin
+2  A: 
SELECT 
    CAST(Time as DATE) EodDate, 
    (
        SELECT  TOP 1
                Value
        FROM    RealtimeData I
        WHERE   CAST(I.Time AS Date) = CAST(O.Time AS Date)
        ORDER BY    Time DESC
    ) EodValue
FROM 
    RealtimeData O
GROUP BY CAST(Time as DATE)
ORDER BY CAST(Time as DATE)
Sam
The `DATE` datatype is new with SQL Server 2008.
ongle
@ongle, thanks for pointing that out. I didn't realize. Anyways, there are other simple ways to get the date component if you need something that's not sql2008 specific.
Sam
A: 

Using Sql 92 is the best solution for anyone who dont want to use specified DB system.

Like this:

Select A.*
From RealtimeData A
Where A.RTime >= (
    select Max(B.RTime)
    From RealtimeData B
    Where Cast((B.RTime - A.RTime) as int) <= 0
)
silent.hill
Very banana. No optimization.
Lu Lu
A: 

;With wcte as ( Select vTime,vValue,Row_Number() over (partition by Convert(DateTime,Convert(varchar(10),vTime,110)) order by vTime Desc) rno from @vTable )Select vTime,vValue from wcte where rno = 1

Atif Sheikh