Странная периодическая группа по задачам (ORA-00979) - PullRequest
3 голосов
/ 04 августа 2011

Мы используем следующий SQL-запрос для получения среднемесячных значений. Этот оператор интенсивно используется и работает довольно хорошо, но он завершается неудачно с 'ORA-00979: не выражением GROUP BY' каждый месяц или два, и мы понятия не имеем, почему.

Сначала о процессе:

  • у нас есть необработанные данные каждые несколько минут,
  • => исходные данные усредняются до часовых, дневных, месячных и годовых значений

необработанные -> ежечасно

  • создает записи в таблице средних значений с типом Average_type 2
  • никогда не бывает проблем

ежечасно => ежедневно / ежедневно => ежемесячно / ежемесячно => ежегодно

  • Заявления очень похожи
  • средние значения «более низкого» типа усредняются для более высокого типа
  • Средние типы: 2 часа, 3 дня, (4 недели не используются), 5 месяцев и 6 лет

  • Ошибка появляется только с шагом «ежедневно => ежемесячно».

Запрос:

  • Мы не можем воспроизвести ошибку, следующий запуск задания агрегации обычно работает без проблем.
  • Ошибки появляются каждые 50-60 дней, без реальной картины
  • Среда: Oracle 10g

Кто-нибудь знает, в чем может быть проблема?

INSERT INTO averages
SELECT averages_seq.NEXTVAL,
       avg.*
FROM (
  SELECT
      m.city_id,            m.city_name,
      m.state_id,           m.state_name,
      m.district_id,        m.district_name,
      m.country_id,         m.country_name,
      m.currency_id,        m.currency_name,
      m.category_id,        m.category_name,
      5 average_type, -- average_type 5 ==> monthly average
      0 analysis_type,
      TRUNC(m.average_date, 'MM')  average_date,
      AVG(m.value) value,
      SUM(m.sum) sum,
      NULL uncertainty,
      NULL uncertainty_type,
      MIN(m.value_min) value_min,
      MAX(m.value_max) value_max,
      SUM(number_of_measurements) number_of_measurements,
      -- 6 * 24 => measurements per day
      -- (ADD_MONTHS(...)) => days per month 
      100 * SUM(number_of_measurements) / 
           (6 * 24 *
           (ADD_MONTHS(TRUNC(average_date, 'MM'), 1)  - TRUNC(average_date, 'MM'))) coverage_percent,
      SUM(customers) customers,
      NULL dummy_field,
      CURRENT_TIMESTAMP calculation_date,
      CURRENT_TIMESTAMP creation_date,
      'AGGREGATION' creation_user,
      CURRENT_TIMESTAMP modification_date,
      'AGGREGATION' modification_user,
      'n' constant_1,
      3   constant_2,
      -1 average_state
  FROM averages m
  WHERE   m.average_type = 3 -- average type 3 ==> daily average
  AND     m.average_date
      BETWEEN
        TO_TIMESTAMP('2011-06-01T00:00:00Z', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
        AND
        TO_TIMESTAMP('2011-06-30T23:59:59Z', 'YYYY-MM-DD"T"HH24:MI:SS"Z"')
  AND     m.analysis_type = 0
  GROUP BY
        m.city_id,            m.city_name,
        m.state_id,           m.state_name,
        m.district_id,        m.district_name,
        m.country_id,         m.country_name,
        m.currency_id,        m.currency_name,
        m.category_id,        m.category_name,
        TRUNC(m.average_date, 'MM')
  ) avg

Ответы [ 2 ]

1 голос
/ 04 августа 2011

Я бы добавил группу следующим образом:

(ADD_MONTHS(TRUNC(average_date, 'MM'), 1)  - TRUNC(average_date, 'MM'))

Я знаю, что это не может измениться без изменения TRUNC(m.average_date, 'MM'), но, похоже, это единственный неагрегированный столбец, отсутствующий в вашем GROUP BY.

Кроме того, вы можете удалить все неагрегированные, постоянные столбцы вне внутреннего sql, а также явно указать имена столбцов, которые вы вставляете, и одновременно выбрать эти константы:

например.

INSERT INTO averages(city_id, city_name, ...average_type, analysis_type, ...)
SELECT averages_seq.NEXTVAL,
avg.city_id, avg.city_name, ...
5, 0, ...

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

0 голосов
/ 05 августа 2011

Судя по сравнению, средняя_дата - это временная метка с часовым поясом (местный часовой пояс?), Но TRUNC работает с датой. Мне интересно, что произойдет, если будет какая-то странность, когда выбранная дата «прыгает» из одного месяца в другой (например, это произошло в январе в одном часовом поясе, а в феврале - в другом).

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

Я бы расширил предложение Геррата об указании имен столбцов, чтобы вы могли выделить константы

INSERT INTO averages
  (average_type, analysis_type, uncertainty, uncertainty_type,
  dummy_field, calculation_date, creation_date, creation_user, 
  modification_date, modification_user, constant_1, constant_2,
   ....
SELECT averages_seq.NEXTVAL,
      5 average_type, -- average_type 5 ==> monthly average
      0 analysis_type,
      NULL uncertainty,
      NULL uncertainty_type,
      NULL dummy_field,
      CURRENT_TIMESTAMP calculation_date,
      CURRENT_TIMESTAMP creation_date,
      'AGGREGATION' creation_user,
      CURRENT_TIMESTAMP modification_date,
      'AGGREGATION' modification_user,
      'n' constant_1,
      3   constant_2,
      -1 average_state
       avg.*
FROM (
  SELECT ...
...