Question

I have a data set of weather temperature data that has a record for every 5 minute interval. I'd like to aggregate this to 15 minute data. To do this I need to group the time intervals by date, hour, and minutes so for the minutes I am group readings taken on the following minute interval {5, 10, 15}, {20, 25, 30}, {35, 40, 45}, {50, 55, 60}. For each group of three readings I should take the average value.

My data has a time stamp in the form of 'DD-MMM-YY HH.MM,' so I have extracted the date, hours, and minutes. I wrote a Case to group the time stamps, which hasn't worked quite right and I am not sure how to build in the average function into the case.

  Select
  Temperature,
  Extract(Minute From Reading_Time) As Minutes,
  Extract(Hour From Reading_Time) As Hours,
  Cast(Reading_Time As Date) As Calendar_Date
  From Weather_Data Where Weather_Station='BDX'    
  Case
    When (Minutes>5 And Minutes<=15)  Then
    To_Timestamp(Calendar_Date &' '&'0'&Hours&':15', 'dd-mon-yy hh24:mi')
    When (Minutes>20 And Minutes<=30)  Then
    To_Timestamp(Calendar_Date &' '&'0'&Hours&':30', 'dd-mon-yy hh24:mi')
    When (Minutes>35 And Minutes<=45)  Then
    To_Timestamp(Calendar_Date &' '&'0'&Hours&':45', 'dd-mon-yy hh24:mi')
    When (Minutes>50 And Minutes<=60)  Then
    To_Timestamp(Calendar_Date &' '&'0'&Hours&':60', 'dd-mon-yy hh24:mi')
End

Modified code with Gordon's feedback. I also rewrote the case logic to correct for a slight offset in time.

select t.*,
(Case When Minutes <= 15 AND Minutes > 0
         Then To_Timestamp(Calendar_Date  &' '&Hours&':15', 'dd-mon-yy hh24:mi')
         When Minutes <= 30 AND Minutes > 0
         Then To_Timestamp(Calendar_Date &' '&Hours&':30', 'dd-mon-yy hh24:mi')
         When Minutes <= 45 AND Minutes > 0
         Then To_Timestamp(Calendar_Date &' '&Hours&':45', 'dd-mon-yy hh24:mi')
         When Minutes = 0 
         Then To_Timestamp(Calendar_Date &' '&Hours&':00', 'dd-mon-yy hh24:mi')
         Else To_Timestamp(Calendar_Date &' '&(Hours+1)&':00', 'dd-mon-yy hh24:mi')
   End) As Aggregated_Timestamp
 from (Select average(Temperature), Extract(Minute From Reading_Time) As Minutes,
         Extract(Hour From Reading_Time) As Hours, Cast(Reading_Time As Date) As    Calendar_Date
  From Weather_Data
  Where Weather_Station = 'BDX'
  Group by Aggregated_Time
 ) t 
Was it helpful?

Solution

Your case is just lingering after your query. The easiest way to write this is with a subquery:

select t.*,
       (Case When (Minutes>5 And Minutes<=15) 
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':15', 'dd-mon-yy hh24:mi')
             When (Minutes>20 And Minutes<=30)
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':30', 'dd-mon-yy hh24:mi')
             When (Minutes>35 And Minutes<=45)
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':45', 'dd-mon-yy hh24:mi')
             When (Minutes>50 And Minutes<=60)
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':60', 'dd-mon-yy hh24:mi')
       End)
from (Select Temperature, Extract(Minute From Reading_Time) As Minutes,
             Extract(Hour From Reading_Time) As Hours, Cast(Reading_Time As Date) As Calendar_Date
      From Weather_Data
      Where Weather_Station = 'BDX'
     ) t 

I don't fully understand your logic, because you have gaps. I would simply write:

       (Case When Minutes <= 15
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':15', 'dd-mon-yy hh24:mi')
             When Minutes <= 30
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':30', 'dd-mon-yy hh24:mi')
             When Minutes <= 45
             Then To_Timestamp(Calendar_Date &' '&'0'&Hours&':45', 'dd-mon-yy hh24:mi')
             else To_Timestamp(Calendar_Date &' '&'0'&Hours&':60', 'dd-mon-yy hh24:mi')
       End)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top