Oracle - SQL, время тянется из диапазона дат - PullRequest
1 голос
/ 20 октября 2011

Я пытаюсь написать оператор выбора, чтобы получить средние значения за определенный период времени за определенный диапазон дат. Например, я хотел бы знать среднее значение (max_percent_util) за последние 7 дней в течение промежутков времени 16: 00-11: 00, весь день и с 8:00 до 18:00. Это то, что я имею до сих пор, и я не уверен, что запрос когда-либо закончится на этом этапе.

select 
sdpt.DOWN_DESC, 
avg(sdpt.max_percent_util) seven_day_prime,
avg(sday.max_percent_util) seven_day,
avg(sdb.max_percent_util) seven_day_business

from 

(select down_desc, hour_stamp, max_percent_util from downstream_hour_facts 
where ((hour_stamp >= sysdate-8 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-7 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-6 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-5 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-4 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-3 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-2 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00')
or (hour_stamp >= sysdate-1 AND to_char(hour_stamp, 'HH24:MI') >= '16:00' AND to_char(hour_stamp, 'HH24:MI') <= '23:00'))) sdpt,

(select down_desc, hour_stamp, max_percent_util from downstream_hour_facts 
where ((hour_stamp >= sysdate-8) or (hour_stamp >= sysdate-7) or (hour_stamp >= sysdate-6)
or (hour_stamp >= sysdate-5) or (hour_stamp >= sysdate-4) or (hour_stamp >= sysdate-3)
or (hour_stamp >= sysdate-2) or (hour_stamp >= sysdate-1))) sday,

(select down_desc, hour_stamp, max_percent_util from downstream_hour_facts 
where ((hour_stamp >= sysdate-8 AND to_char(hour_stamp, 'HH24:MI') >= '8:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-7 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-6 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-5 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-4 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-3 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-2 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00')
or (hour_stamp >= sysdate-1 AND to_char(hour_stamp, 'HH24:MI') >= '08:00' AND to_char(hour_stamp, 'HH24:MI') <= '18:00'))) sdb
where sdpt.down_desc = sday.down_desc and sday.down_desc = sdb.down_desc
group by sdpt.DOWN_DESC
order by sdpt.down_desc

Пример вывода, который я хочу воссоздать:

  • Метрика: данные об использовании
  • Предыдущие 24 часа: 7,15%
  • 7-дневный прокат (все часы): 7,12%
  • 7-дневное скользящее прайм-тайм (4-12): 7,12%
  • 7-дневные рабочие часы (9-5): 7,12%

1 Ответ

3 голосов
/ 20 октября 2011

Одна из причин, по которой ваш запрос слишком медленный, заключается в том, что вы не проводите кампанию по датам, а сравниваете строки;используя TO_CHAR ().Вы также выполняете много лишней работы.

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

WITH
  filtered_data AS
(
  SELECT
    down_desc,
    hour_stamp,
    TRUNC(hour_stamp)                date_stamp,
    hour_stamp - TRUNC(hour_stamp)   time_stamp
  FROM
    downstream_hour_facts
  WHERE
    hour_stamp >= TRUNC(sysdate) - 8
)
SELECT
  down_desc,
  AVG(CASE WHEN date_stamp >= TRUNC(sysdate)
           THEN max_percent ELSE NULL END)          today,
  AVG(CASE WHEN date_stamp <  TRUNC(sysdate)
           THEN max_percent ELSE NULL END)          seven_day_all,
  AVG(CASE WHEN date_stamp <  TRUNC(sysdate)
            AND time_stamp >= TO_TIMESTAMP('16:00', 'HH24:MI')
            AND time_stamp <  TO_TIMESTAMP('23:00', 'HH24:MI')
           THEN max_percent ELSE NULL END)          seven_day_prime,
  AVG(CASE WHEN date_stamp <  TRUNC(sysdate)
            AND time_stamp >= TO_TIMESTAMP('08:00', 'HH24:MI')
            AND time_stamp <  TO_TIMESTAMP('16:00', 'HH24:MI')
           THEN max_percent ELSE NULL END)          seven_day_business
FROM
  filtered_data
GROUP BY
  down_desc
ORDER BY
  down_desc


РЕДАКТИРОВАТЬ

Я также заметил, что вы объединяете данные в 'опасно «неправильный путь ...

Подзапрос 1 может вернуть 9 записей для метрики.Подзапрос 2 может вернуть 3 записи для этого показателя.Подзапрос 3 может вернуть 4 записи для этой метрики.

Но тогда вы присоединитесь к ним only по метрике.Все 9 записей из SQ1 соответствуют всем 3 из SQ2 (сейчас 27 записей), и все они соответствуют всем 4 из SQ3 (сейчас 108 записей).

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

(вышеприведенная версия с разбором должна полностью избежать этой проблемы).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...