PostgreSQL Numeri c Ошибка переполнения поля - поле с точностью 10, шкала 1 должно округляться до абсолютного значения менее 10 ^ 9 - PullRequest
0 голосов
/ 27 марта 2020

Пожалуйста, я пытаюсь найти процентную разницу между двумя значениями суммы imls2016.visits и суммой imls2010.visits в каждой строке. Который ранее работал нормально, прежде чем я добавил третью таблицу в моем совместном заявлении (таблица imls_regions). Но всякий раз, когда я запускаю новый код, он выдает ошибку переполнения цифры c. Я настроил точность и масштаб, но мне не удалось исправить эту ошибку. Пожалуйста, что я должен изменить в своем коде: (PostgreSQL 12)

  • Сообщение об ошибке:> «ОШИБКА: цифра c переполнение поля ДЕТАЛИ: Поле с точностью 10, шкала 1 должно округляться до абсолютное значение меньше 10 ^ 9. SQL состояние: 22003 "

Мой код:

SELECT imlsreg.obereg,
        imlsreg.obereg_name,
        SUM(imls2016.visits) AS total_visits_2016,
        SUM(imls2010.visits) AS total_visits_2010,
        ROUND((CAST(SUM(imls2016.visits) AS decimal(10, 1)) - SUM(imls2010.visits)) / SUM(imls2010.visits) * 100, 1) AS pct_change_in_visits
FROM imls_regions AS imlsreg INNER JOIN imls_library_survey_2016 AS imls2016
ON imlsreg.obereg = imls2016.obereg
INNER JOIN imls_library_survey_2010 AS imls2010
ON imlsreg.obereg = imls2010.obereg
WHERE imls2016.visits >= 0 AND imls2010.visits >= 0
GROUP BY imlsreg.obereg, imlsreg.obereg_name
ORDER BY pct_change_in_visits ASC;

Ответы [ 2 ]

1 голос
/ 27 марта 2020

Когда вы приводите значение decimal(10,1), вы уменьшаете диапазон допустимых значений SUM(imls2016.visits) в обмен на большую точность, но это приводит к переполнению вашего результата.

Есть две вещи, которые вы можете do:

  1. Выполнение приведения после вычисления SUM(imls2016.visits) - SUM(imls2010.visits)
  2. Снижение точности приведения.

Реализация первого может быть достаточно, и вы бы определили pct_change_in_visits как:

ROUND(CAST(SUM(imls2016.visits) - SUM(imls2010.visits) AS decimal(10, 1)) / SUM(imls2010.visits) * 100, 1) AS pct_change_in_visits
0 голосов
/ 27 марта 2020

Хорошо, я нашел проблему. Мое значение суммы имело точность более 10 (это означает, что сумма, которая в целочисленном формате имела длину 12 значений), следовательно, при приведении к ней выдает ошибку переполнения поля Numeri c. Чтобы выяснить, где я ошибся, я удалил функции ROUND () И CAST () в листинге 1.1:

  • в листинге 1.1:
SELECT imlsreg.obereg,
        imlsreg.obereg_name,
        SUM(imls2016.visits) AS total_visits_2016,
        SUM(imls2010.visits) AS total_visits_2010,
        (SUM(imls2016.visits) - SUM(imls2010.visits)) / SUM(imls2010.visits) * 100 AS pct_change_in_visits
FROM imls_regions AS imlsreg INNER JOIN imls_library_survey_2016 AS imls2016
ON imlsreg.obereg = imls2016.obereg
INNER JOIN imls_library_survey_2010 AS imls2010
ON imlsreg.obereg = imls2010.obereg
WHERE imls2016.visits >= 0 AND imls2010.visits >= 0
GROUP BY imlsreg.obereg, imlsreg.obereg_name
ORDER BY pct_change_in_visits ASC;

Это дало мне сумма посещений, которую я хотел увидеть, но пока игнорирую pct_change (большая часть pct_change равна 0, потому что деление двух целых чисел на sql дает целое число, поэтому важно привести рабочее значение в число с десятичной или двойной точностью c тип данных)

listing 1.1 results

После подсчета количества значений максимального количества посещений (длиной 12) я смог найти точное значение точности. Затем я вернулся к своему предыдущему коду и скорректировал точность до цифры c (14, 1). См. Код в листинге 1.2:

  • Листинг 1.2:
SELECT imlsreg.obereg,
        imlsreg.obereg_name,
        SUM(imls2016.visits) AS total_visits_2016,
        SUM(imls2010.visits) AS total_visits_2010,
        ROUND((CAST(SUM(imls2016.visits) AS decimal(14, 1)) - SUM(imls2010.visits)) / SUM(imls2010.visits) * 100, 2) AS pct_change_in_visits
FROM imls_regions AS imlsreg INNER JOIN imls_library_survey_2016 AS imls2016
ON imlsreg.obereg = imls2016.obereg
INNER JOIN imls_library_survey_2010 AS imls2010
ON imlsreg.obereg = imls2010.obereg
WHERE imls2016.visits >= 0 AND imls2010.visits >= 0
GROUP BY imlsreg.obereg, imlsreg.obereg_name
ORDER BY pct_change_in_visits ASC;

listing 1.2

...