Как вернуть значение из столбца A в строке, где в подзапросе найдено значение Max of Column B - PullRequest
0 голосов
/ 01 мая 2019

У меня есть данные временного ряда, и я создаю скользящее среднее по окну 90 выборок (15 минут).Затем я хочу найти максимальное 15-минутное окно каждый час, чтобы данные группировались по часам.Однако я также хочу вернуть отметку времени начала и окончания окна максимум 15 минут.В настоящее время я возвращаю только отметку времени в начале каждого часа.

Вот пример данных, с которых я начинаю:

theDate    theTime     value
4/30/2019   22:47:53    0
4/30/2019   22:47:43    0
4/30/2019   22:47:33    0
4/30/2019   22:47:23    0
4/30/2019   22:47:13    0
4/30/2019   22:47:03    0
4/30/2019   22:46:53    0
4/30/2019   22:46:43    0

Я пробовал row_number () и фильтровалгде, но я не думаю, что я применяю их правильно для этого, так как есть несколько вложенных подзапросов.

select
        min([theDate]) as theDate, 
        min([theTime]) as theTime, 
        max([Value]) as maxValue, 
        max([rolling_avg]) as maxDM,
        timeHour as timeHour

from( select [theDate], [theTime], [Value],
       avg(windowAvg) over(order by theDate DESC, theTime rows between 90 preceding and current row) as rolling_avg,
       datepart(hh,theTime) as timeHour
  from (select [theDate], [theTime], [Value], sum([Value]) as windowAvg
          from [Data].[dbo].[tOne]
          Where ([theDate] > convert(DAte,DATEADD(month, -1, GETDATE())))
          group by theDate, theTime, Value 

          )tOneTemp   
          )tOneTempTwo
          group by theDate, timeHour
          order by theDate DESC, theTime DESC

Я ищу таблицу ниже, за исключением того, что вместо времени всегда будет минимум в частак как я рассчитал его, я бы хотел, чтобы оно было значением в пределах 15-минутного окна того, что было рассчитано MaxDM.

Вот пример того, что я получаю, используя свой текущий код:

theDate    theTime   maxValue   maxDM       timeHour
2019-04-30  22:00:04    508.8   660.643956  22
2019-04-30  21:00:03    1071.3  798.206593  21
2019-04-30  20:00:03    1022.2  817.539560  20
2019-04-30  19:00:04    871.4   574.786813  19
2019-04-30  18:00:04    944.0   670.095604  18

То, что я хотел бы видеть, - это что-то вроде этого, так что «theTime» отражает начало окна «maxValue».

Вот пример того, что я хотел бы видеть (* notetheTime):

theDate    theTime   maxValue   maxDM       timeHour
2019-04-30  22:10:34    508.8   660.643956  22
2019-04-30  21:45:03    1071.3  798.206593  21
2019-04-30  20:12:03    1022.2  817.539560  20
2019-04-30  19:32:04    871.4   574.786813  19
2019-04-30  18:56:04    944.0   670.095604  18

Спасибо Али, вот несколько модов, которые я сделал для вашего кода, чтобы исправить некоторые ошибки, но «TheTimeOfMaxDM» возвращается как «NULL» для всех строк.

                    min([theDate]) as theDate, 
                    min([theTime]) as theTime, 
                    (select top(1) r.[theTime] from RunningAvg15Min r where 
                        r.[theDate]=(select min([theDate]) from RunningAvg15Min) and
                        r.[theTime]>=(select min([theTime]) from RunningAvg15Min)
                        and r.rolling_avg=(select max([rolling_avg]) from RunningAvg15Min)) as TheTimeOfMaxDM,
                    max([KW]) as maxValue, 
                    max([rolling_avg]) as maxDM,
                    timeHour as timeHour
                from RunningAvg15Min
                GROUP BY theDate, timeHour
                ORDER BY thedate DESC, thetime DESC

1 Ответ

0 голосов
/ 03 мая 2019

Я переписал ваш запрос в CTE, чтобы снова использовать подзапрос.пожалуйста, проверьте следующее: - поэтому я добавил еще один вывод в ваш запрос под названием TheTimeOfMaxDM.Надеюсь, это то, что вам нужно.

;with LastMonthData as (
               --get the data for the last month, and sum value if same time stamp is recorded (this is not logical)
               select [theDate], [theTime], [Value], sum([Value]) as windowAvg
                  from [tOne]
                  Where ([theDate] > convert(Date,DATEADD(month, -1, '2019-05-3')))--changed this to match the data provided.
                  group by theDate, theTime, Value 
          ),
RunningAvg15Min as (
                    select [theDate], [theTime], [Value],
                    avg(windowAvg) over(order by theDate DESC, theTime rows between 90 preceding and current row) as rolling_avg,
                    datepart(hh,theTime) as timeHour
                from LastMonthData
              ),DataSetGrouping as (
              select
                    min([theDate]) as theDate, 
                    min([theTime]) as theTime, 
                    min(datepart(hh,theTime)) as timeHour,
                    max([Value]) as maxValue, 
                    max([rolling_avg]) as maxDM
                from RunningAvg15Min
                GROUP BY
                    DATEPART(YEAR, TheDate),
                    DATEPART(MONTH, TheDate),
                    DATEPART(DAY, TheDate),
                    DATEPART(HOUR, TheTime),
                    (DATEPART(MINUTE, TheTime) / 60) ---change the 60 to 15, to change the grouping from per hour to per 15min

                )
                select * ,
                 (select top(1) r.[theTime] from RunningAvg15Min r where 
                        r.[theDate]=theDate
                        and r.[theTime]>=theTime
                        and r.rolling_avg=maxDM
                        order by r.[theDate],r.[theTime]
                        )  [TheTimeOfMaxDM]
                from DataSetGrouping
                ORDER BY thedate DESC, thetime DESC

Еще одно замечание, я не знаю, нужно ли вам это или нет, но если вы хотите сгруппировать по 15 минут, вы можете использовать ниже в разделе группировки

GROUP BY
    DATEPART(YEAR, TheDate),
    DATEPART(MONTH, TheDate),
    DATEPART(DAY, TheDate),
    DATEPART(HOUR, TheTime),
    (DATEPART(MINUTE, TheTime) / 15)

Я попытаюсь проверить точку, возьмем, к примеру, следующую строку вывода: -

theDate     theTime             Value   rolling_avg         timeHour
2019-04-07  17:20:49.0000000    398.3   314.499999999997    17

В 2019-04-07 между 17 и 18 часами максимальное значение roll_avg равно314.499999999997, и время для этого максимума было 17: 20: 49.0000000, мы можем видеть, что мы заменили последнюю часть cte следующим: -

select * from RunningAvg15Min where rolling_avg between 314 and 315
                and thedate='2019-04-07' and theTime between '17:00:00' and '18:00:00'

output

theDate      theTime            Value   rolling_avg         timeHour
2019-04-07  17:20:49.0000000    398.3   314.499999999997    17

Подводя итог моему ответу, вы можете использовать CTE в моде из запроса, который я написал, чтобы упростить подзапросы и ссылаться на них более одного раза в вашем запросе, если это необходимо.надеюсь, это поможет.

...