LOG в PostgreSQL считает логарифм числа.
Если по-простому, логарифм отвечает на вопрос:
В какую степень нужно возвести основание, чтобы получить это число?
Например:
SELECT
LOG(100) AS result;
Результат будет 2, потому что:
10^2 = 100
То есть LOG(100) в PostgreSQL означает «логарифм 100 по основанию 10».
На практике логарифмы нужны не только математикам. В SQL они пригождаются в отчётах, аналитике и графиках, когда значения слишком сильно отличаются друг от друга: один заказ на 100, другой на 100000, третий на 10000000. Обычная шкала в таком случае растягивается, а логарифм помогает аккуратно сжать значения и увидеть картину.
Но у LOG есть важная ловушка: в PostgreSQL LOG(x) — это десятичный логарифм, а в MySQL LOG(x) — натуральный логарифм. Один и тот же запрос в разных базах может молча вернуть разные числа.
Разберём спокойно: как работает LOG, чем он отличается от LN, где его применять и как не попасть в неприятную несовместимость между СУБД.
Что такое логарифм простыми словами
Логарифм — это обратная операция к возведению в степень.
Если:
10^3 = 1000
то:
log10(1000) = 3
Потому что вопрос такой:
В какую степень нужно возвести 10, чтобы получить 1000?
Ответ: в третью.
Ещё пример:
2^10 = 1024
Значит:
log2(1024) = 10
В SQL это можно посчитать так:
SELECT
LOG(2, 1024) AS result;
Результат:
10
Именно поэтому логарифм удобно использовать там, где нас интересует не само число, а его порядок величины.
Две формы LOG в PostgreSQL
В PostgreSQL у LOG есть две формы.
Первая форма:
LOG(x)
Она считает логарифм x по основанию 10.
Вторая форма:
LOG(b, x)
Она считает логарифм x по основанию b.
Примеры:
SELECT
LOG(100) AS a,
LOG(1000) AS b,
LOG(2, 8) AS c,
LOG(2, 1024) AS d;
Результат будет примерно таким:
Почему?
LOG(100) равно 2, потому что 10^2 = 100;
LOG(1000) равно 3, потому что 10^3 = 1000;
LOG(2, 8) равно 3, потому что 2^3 = 8;
LOG(2, 1024) равно 10, потому что 2^10 = 1024.
Запомните порядок аргументов:
LOG(base, value)
Сначала основание, потом число.
LOG(x) в PostgreSQL — это основание 10
Это нужно запомнить отдельно.
В PostgreSQL:
SELECT
LOG(100) AS result;
вернёт 2.
Потому что PostgreSQL считает:
log10(100)
То есть логарифм по основанию 10.
Если нужен натуральный логарифм, по основанию e, используйте не LOG, а LN.
SELECT
LN(100) AS result;
Результат будет примерно:
4.60517018598809
Для новичка здесь главный вывод такой:
В PostgreSQL LOG(x) и LN(x) — не одно и то же.
LOG(x) — десятичный логарифм.
LN(x) — натуральный логарифм.
Главная ловушка: в MySQL LOG(x) означает другое
Вот место, где часто ошибаются при переносе запросов между базами.
В PostgreSQL:
SELECT
LOG(100) AS result;
вернёт 2.
А в MySQL похожий запрос вернёт примерно 4.605, потому что в MySQL LOG(x) с одним аргументом означает натуральный логарифм.
То есть:
| СУБД |
LOG(100) означает |
Результат |
| PostgreSQL |
log10(100) |
2 |
| MySQL |
ln(100) |
4.605... |
И это особенно неприятно, потому что ошибки не будет. Запрос выполнится. Просто результат окажется другим.
Поэтому в переносимом SQL лучше не писать одинокий LOG(x), если есть риск, что запрос будет жить в разных СУБД.
Лучше писать явно.
Для десятичного логарифма:
SELECT
LOG10(100) AS result;
Для натурального логарифма:
SELECT
LN(100) AS result;
Так намерение видно сразу.
LOG10 и LN: безопасные имена
Если вам нужен логарифм по основанию 10, используйте LOG10.
SELECT
LOG10(1000) AS result;
Результат:
3
Если нужен натуральный логарифм, используйте LN.
SELECT
LN(1000) AS result;
Такой код легче читать и безопаснее переносить.
Даже в PostgreSQL, где LOG(1000) и LOG10(1000) дадут одно и то же, второй вариант иногда понятнее:
SELECT
LOG10(amount) AS amount_log10
FROM orders;
По названию сразу видно: речь про основание 10.
Ограничения: число должно быть положительным
Логарифм нельзя посчитать для нуля и отрицательных чисел.
В PostgreSQL такой запрос упадёт с ошибкой:
SELECT
LOG(0) AS result;
И такой тоже:
SELECT
LOG(-5) AS result;
LOG не вернёт аккуратный NULL. Он остановит выполнение запроса ошибкой.
Поэтому перед логарифмом всегда нужно убедиться, что значение строго больше нуля.
Например:
SELECT
id,
LOG(amount) AS amount_log
FROM orders
WHERE amount > 0;
Если в таблице могут быть возвраты, скидки, нулевые суммы или технические записи, фильтр обязателен.
Как безопасно считать LOG для грязных данных
Иногда вы не хотите выкидывать строки из результата, но хотите считать логарифм только там, где это возможно.
Тогда удобно использовать CASE.
SELECT
id,
amount,
CASE
WHEN amount > 0 THEN LOG(amount)
ELSE NULL
END AS amount_log
FROM orders;
Так запрос не упадёт.
Для положительных сумм он посчитает логарифм, для нуля и отрицательных значений вернёт NULL.
Иногда для защиты от нуля используют NULLIF.
SELECT
id,
LOG(NULLIF(amount, 0)) AS amount_log
FROM orders;
Но этот вариант защищает только от нуля. Если в данных есть отрицательные числа, запрос всё равно может упасть. Поэтому универсальнее писать через CASE WHEN amount > 0.
Основание тоже должно быть правильным
Во второй форме:
LOG(b, x)
важны оба числа.
x должен быть строго больше нуля.
Основание b тоже должно быть строго больше нуля и не должно быть равно 1.
Почему основание 1 нельзя?
Потому что 1 в любой степени остаётся 1.
1^1 = 1
1^2 = 1
1^100 = 1
Из такого основания нельзя нормально получить, например, 8 или 100.
Поэтому такие значения для основания не подходят.
Правильные примеры:
SELECT
LOG(2, 8) AS log2_8,
LOG(10, 1000) AS log10_1000,
LOG(5, 125) AS log5_125;
Где LOG полезен в реальных задачах
Логарифмы особенно полезны, когда значения отличаются на порядки.
Например, есть суммы заказов:
| amount |
5 |
20 |
300 |
7000 |
120000 |
На обычной шкале маленькие суммы почти исчезнут рядом с большими. Логарифм сжимает шкалу и помогает группировать значения по порядку величины.
Порядок величины — это примерно ответ на вопрос:
Число ближе к единицам, десяткам, сотням, тысячам или миллионам?
Например:
1–9 — порядок 0;
10–99 — порядок 1;
100–999 — порядок 2;
1000–9999 — порядок 3.
Для этого удобно использовать LOG10 или LOG в PostgreSQL.
Корзины по порядку величины
Допустим, нужно понять, как распределены оплаченные заказы по размеру суммы.
SELECT
FLOOR(LOG(amount))::int AS magnitude,
COUNT(*) AS orders_count
FROM orders
WHERE status = 'paid'
AND amount > 0
GROUP BY FLOOR(LOG(amount))::int
ORDER BY magnitude;
Что делает запрос:
- Берёт только оплаченные заказы.
- Отбрасывает неположительные суммы.
- Считает десятичный логарифм суммы.
- Округляет вниз через
FLOOR.
- Группирует заказы по порядку величины.
Пример результата:
| magnitude |
orders_count |
0 |
18 |
1 |
240 |
2 |
810 |
3 |
135 |
4 |
9 |
Как это читать:
0 — суммы от 1 до 9;
1 — суммы от 10 до 99;
2 — суммы от 100 до 999;
3 — суммы от 1000 до 9999;
4 — суммы от 10000 до 99999.
Это очень удобно для быстрых аналитических срезов.
Почему тут нужен FLOOR
LOG(500) не равен целому числу.
Он примерно равен 2.699.
Потому что 500 лежит между 100 и 1000.
10^2 = 100
10^3 = 1000
Чтобы превратить логарифм в номер корзины, мы берём FLOOR.
SELECT
FLOOR(LOG(500)) AS magnitude;
Результат:
2
То есть число 500 попадает в корзину сотен.
Подсчёт количества цифр
Ещё один полезный трюк: через логарифм можно посчитать количество цифр в положительном целом числе.
Формула такая:
floor(log10(n)) + 1
Например:
7 имеет 1 цифру;
42 имеет 2 цифры;
999 имеет 3 цифры;
1000 имеет 4 цифры.
В PostgreSQL:
SELECT
id,
salary,
FLOOR(LOG10(salary))::int + 1 AS digits_count
FROM employees
WHERE salary > 0
ORDER BY salary DESC;
Можно использовать и LOG(salary), потому что в PostgreSQL LOG(x) — это основание 10.
Но LOG10(salary) читается яснее.
SELECT
id,
salary,
FLOOR(LOG10(salary))::int + 1 AS digits_count
FROM employees
WHERE salary > 0;
Такой приём полезен редко, но хорошо показывает смысл логарифма: он помогает понять масштаб числа.
Логарифм для графиков
Логарифм часто используют перед построением графиков.
Например, если на графике есть значения 10, 100, 1000, 1000000, обычная шкала может стать неудобной: маленькие значения прижмутся к нулю, а одно огромное значение растянет весь график.
Логарифм делает так, что расстояния между порядками становятся равными:
- от
10 до 100;
- от
100 до 1000;
- от
1000 до 10000.
В SQL можно заранее подготовить значение для графика:
SELECT
id,
amount,
LOG10(amount) AS amount_log10
FROM orders
WHERE amount > 0;
Потом уже строить график по amount_log10.
Важно: логарифм меняет шкалу. Это не «настоящая сумма», а преобразованное значение. В отчёте лучше явно подписывать такие колонки, чтобы читатель не перепутал.
Связь LOG и LN
LOG, LOG10 и LN считают логарифмы, но с разными основаниями.
В PostgreSQL:
SELECT
LOG(100) AS log_default,
LOG10(100) AS log10_value,
LN(100) AS natural_log;
LOG(100) и LOG10(100) дадут 2.
LN(100) даст примерно 4.605.
Почему LN отдельно?
Потому что натуральный логарифм по основанию e часто используется в математике, статистике, финансах и некоторых аналитических формулах.
Для обычных бизнес-корзин вроде «единицы, десятки, сотни, тысячи» чаще удобнее основание 10.
Как поменять основание вручную
Если в СУБД нет удобной формы LOG(b, x), логарифм по любому основанию можно собрать через формулу смены основания:
log_b(x) = ln(x) / ln(b)
В PostgreSQL это тоже работает:
SELECT
LN(8) / LN(2) AS log2_via_ln,
LOG(2, 8) AS log2_builtin;
Оба результата будут равны 3.
То же самое можно сделать через десятичный логарифм:
SELECT
LOG10(8) / LOG10(2) AS log2_via_log10;
Главное — делить логарифмы, посчитанные в одном и том же основании.
LOG в разных СУБД
Вот короткая таблица, которую стоит держать под рукой.
| Задача |
PostgreSQL |
MySQL |
ClickHouse |
| Десятичный логарифм |
LOG(x) или LOG10(x) |
LOG10(x) |
log10(x) |
| Натуральный логарифм |
LN(x) |
LOG(x) или LN(x) |
log(x) или ln(x) |
| Логарифм по основанию 2 |
LOG(2, x) |
LOG2(x) или LOG(2, x) |
log2(x) |
| Любое основание |
LOG(b, x) |
LOG(b, x) |
log(x) / log(b) |
Главная несовместимость:
SELECT
LOG(100) AS result;
В PostgreSQL это основание 10.
В MySQL это основание e.
Поэтому для переносимого кода лучше писать явно:
SELECT
LOG10(100) AS log10_value,
LN(100) AS natural_log;
Почему лучше не полагаться на умолчания
Допустим, вы написали в PostgreSQL:
SELECT
LOG(amount) AS amount_log
FROM orders;
Вы имели в виду десятичный логарифм.
Потом этот запрос кто-то переносит в MySQL. Запрос не падает. Он продолжает работать. Но теперь LOG(amount) означает натуральный логарифм.
Это опаснее синтаксической ошибки. Синтаксическую ошибку видно сразу, а здесь отчёт может выглядеть правдоподобно, но числа будут другими.
Поэтому хороший стиль:
- для основания
10 писать LOG10(x);
- для основания
e писать LN(x);
- для другого основания писать
LOG(b, x), если СУБД это поддерживает.
Так запрос легче читать и труднее сломать при переносе.
Тип результата и точность
В PostgreSQL LOG для числовых значений возвращает числовой результат с хорошей точностью.
Например:
SELECT
LOG(3) AS result;
Результат будет не целым числом, потому что 3 не является точной степенью 10.
Для большинства учебных и аналитических задач об этом достаточно знать две вещи:
- результат логарифма часто дробный;
- сравнивать такие значения лучше аккуратно, без ожидания идеальной точности до последнего знака.
Если вам нужна высокая производительность на больших объёмах и достаточно приблизительной точности, в реальных проектах иногда отдельно думают о типах данных и приведении к double precision. Но для начинающего главное — сначала правильно понять основание и ограничения по положительным значениям.
Частые ошибки
Первая ошибка — думать, что LOG(x) везде означает одно и то же.
SELECT
LOG(100) AS result;
В PostgreSQL результат будет 2.
В MySQL результат будет примерно 4.605.
Для понятного кода лучше так:
SELECT
LOG10(100) AS result;
Вторая ошибка — считать логарифм от нуля.
SELECT
LOG(0) AS result;
Такой запрос упадёт.
Лучше заранее фильтровать данные:
SELECT
id,
LOG10(amount) AS amount_log10
FROM orders
WHERE amount > 0;
Третья ошибка — защищаться только от нуля, когда в данных бывают отрицательные значения.
SELECT
LOG10(NULLIF(amount, 0)) AS amount_log10
FROM orders;
Если amount = -10, проблема останется.
Надёжнее так:
SELECT
id,
CASE
WHEN amount > 0 THEN LOG10(amount)
ELSE NULL
END AS amount_log10
FROM orders;
Четвёртая ошибка — перепутать порядок аргументов.
В PostgreSQL правильно:
SELECT
LOG(2, 8) AS result;
Это значит:
log2(8)
Результат будет 3.
Пятая ошибка — забывать, что логарифм меняет смысл шкалы.
SELECT
LOG10(amount) AS amount_log10
FROM orders;
Это уже не сумма заказа. Это логарифм суммы. В отчёте такую колонку нужно называть явно, чтобы не вводить людей в заблуждение.
Практический пример: распределение заказов по масштабу
Допустим, у нас есть интернет-магазин. Заказы бывают маленькие, средние и очень крупные. Нужно быстро понять, в каких порядках величины живёт основная масса оплат.
SELECT
FLOOR(LOG10(amount))::int AS magnitude,
COUNT(*) AS orders_count,
MIN(amount) AS min_amount,
MAX(amount) AS max_amount
FROM orders
WHERE status = 'paid'
AND amount > 0
GROUP BY FLOOR(LOG10(amount))::int
ORDER BY magnitude;
Пример результата:
| magnitude |
orders_count |
min_amount |
max_amount |
0 |
12 |
1 |
9 |
1 |
345 |
10 |
99 |
2 |
1280 |
100 |
999 |
3 |
220 |
1000 |
9990 |
4 |
8 |
12000 |
85000 |
Такой отчёт сразу показывает, где основная масса заказов, а где редкие крупные значения.
Для обычной группировки по диапазонам можно было бы написать CASE WHEN. Но логарифм удобен, когда диапазоны идут по степеням десяти: десятки, сотни, тысячи, десятки тысяч.
Главное
LOG в PostgreSQL считает логарифм.
У него есть две основные формы:
SELECT
LOG(x) AS log10_value;
Это логарифм по основанию 10.
SELECT
LOG(b, x) AS custom_base_log;
Это логарифм x по основанию b.
Для натурального логарифма используйте LN.
SELECT
LN(x) AS natural_log;
Самая важная ловушка: LOG(x) в PostgreSQL и LOG(x) в MySQL означают разное.
В PostgreSQL:
LOG(x) = log10(x)
В MySQL:
LOG(x) = ln(x)
Чтобы не путаться, пишите явно:
SELECT
LOG10(amount) AS amount_log10,
LN(amount) AS amount_ln
FROM orders
WHERE amount > 0;
Логарифм можно считать только для положительных значений. Если в данных бывают нули или отрицательные числа, защищайте запрос через WHERE amount > 0 или CASE.
LOG полезен для лог-шкал, группировки по порядкам величины, анализа больших разбросов и подсчёта количества цифр. Но используйте его осознанно: логарифм не просто красиво форматирует число, а меняет шкалу и смысл значения.
LOGв PostgreSQL считает логарифм числа.Если по-простому, логарифм отвечает на вопрос:
Например:
SELECT LOG(100) AS result;Результат будет
2, потому что:То есть
LOG(100)в PostgreSQL означает «логарифм 100 по основанию 10».На практике логарифмы нужны не только математикам. В SQL они пригождаются в отчётах, аналитике и графиках, когда значения слишком сильно отличаются друг от друга: один заказ на
100, другой на100000, третий на10000000. Обычная шкала в таком случае растягивается, а логарифм помогает аккуратно сжать значения и увидеть картину.Но у
LOGесть важная ловушка: в PostgreSQLLOG(x)— это десятичный логарифм, а в MySQLLOG(x)— натуральный логарифм. Один и тот же запрос в разных базах может молча вернуть разные числа.Разберём спокойно: как работает
LOG, чем он отличается отLN, где его применять и как не попасть в неприятную несовместимость между СУБД.Что такое логарифм простыми словами
Логарифм — это обратная операция к возведению в степень.
Если:
то:
Потому что вопрос такой:
Ответ: в третью.
Ещё пример:
Значит:
В SQL это можно посчитать так:
SELECT LOG(2, 1024) AS result;Результат:
Именно поэтому логарифм удобно использовать там, где нас интересует не само число, а его порядок величины.
Две формы LOG в PostgreSQL
В PostgreSQL у
LOGесть две формы.Первая форма:
LOG(x)Она считает логарифм
xпо основанию10.Вторая форма:
LOG(b, x)Она считает логарифм
xпо основаниюb.Примеры:
SELECT LOG(100) AS a, LOG(1000) AS b, LOG(2, 8) AS c, LOG(2, 1024) AS d;Результат будет примерно таким:
23310Почему?
LOG(100)равно2, потому что10^2 = 100;LOG(1000)равно3, потому что10^3 = 1000;LOG(2, 8)равно3, потому что2^3 = 8;LOG(2, 1024)равно10, потому что2^10 = 1024.Запомните порядок аргументов:
LOG(base, value)Сначала основание, потом число.
LOG(x) в PostgreSQL — это основание 10
Это нужно запомнить отдельно.
В PostgreSQL:
SELECT LOG(100) AS result;вернёт
2.Потому что PostgreSQL считает:
То есть логарифм по основанию
10.Если нужен натуральный логарифм, по основанию
e, используйте неLOG, аLN.SELECT LN(100) AS result;Результат будет примерно:
Для новичка здесь главный вывод такой:
LOG(x)— десятичный логарифм.LN(x)— натуральный логарифм.Главная ловушка: в MySQL LOG(x) означает другое
Вот место, где часто ошибаются при переносе запросов между базами.
В PostgreSQL:
SELECT LOG(100) AS result;вернёт
2.А в MySQL похожий запрос вернёт примерно
4.605, потому что в MySQLLOG(x)с одним аргументом означает натуральный логарифм.То есть:
LOG(100)означаетlog10(100)2ln(100)4.605...И это особенно неприятно, потому что ошибки не будет. Запрос выполнится. Просто результат окажется другим.
Поэтому в переносимом SQL лучше не писать одинокий
LOG(x), если есть риск, что запрос будет жить в разных СУБД.Лучше писать явно.
Для десятичного логарифма:
SELECT LOG10(100) AS result;Для натурального логарифма:
SELECT LN(100) AS result;Так намерение видно сразу.
LOG10 и LN: безопасные имена
Если вам нужен логарифм по основанию
10, используйтеLOG10.SELECT LOG10(1000) AS result;Результат:
Если нужен натуральный логарифм, используйте
LN.SELECT LN(1000) AS result;Такой код легче читать и безопаснее переносить.
Даже в PostgreSQL, где
LOG(1000)иLOG10(1000)дадут одно и то же, второй вариант иногда понятнее:SELECT LOG10(amount) AS amount_log10 FROM orders;По названию сразу видно: речь про основание
10.Ограничения: число должно быть положительным
Логарифм нельзя посчитать для нуля и отрицательных чисел.
В PostgreSQL такой запрос упадёт с ошибкой:
SELECT LOG(0) AS result;И такой тоже:
SELECT LOG(-5) AS result;LOGне вернёт аккуратныйNULL. Он остановит выполнение запроса ошибкой.Поэтому перед логарифмом всегда нужно убедиться, что значение строго больше нуля.
Например:
SELECT id, LOG(amount) AS amount_log FROM orders WHERE amount > 0;Если в таблице могут быть возвраты, скидки, нулевые суммы или технические записи, фильтр обязателен.
Как безопасно считать LOG для грязных данных
Иногда вы не хотите выкидывать строки из результата, но хотите считать логарифм только там, где это возможно.
Тогда удобно использовать
CASE.SELECT id, amount, CASE WHEN amount > 0 THEN LOG(amount) ELSE NULL END AS amount_log FROM orders;Так запрос не упадёт.
Для положительных сумм он посчитает логарифм, для нуля и отрицательных значений вернёт
NULL.Иногда для защиты от нуля используют
NULLIF.SELECT id, LOG(NULLIF(amount, 0)) AS amount_log FROM orders;Но этот вариант защищает только от нуля. Если в данных есть отрицательные числа, запрос всё равно может упасть. Поэтому универсальнее писать через
CASE WHEN amount > 0.Основание тоже должно быть правильным
Во второй форме:
LOG(b, x)важны оба числа.
xдолжен быть строго больше нуля.Основание
bтоже должно быть строго больше нуля и не должно быть равно1.Почему основание
1нельзя?Потому что
1в любой степени остаётся1.Из такого основания нельзя нормально получить, например,
8или100.Поэтому такие значения для основания не подходят.
Правильные примеры:
SELECT LOG(2, 8) AS log2_8, LOG(10, 1000) AS log10_1000, LOG(5, 125) AS log5_125;Где LOG полезен в реальных задачах
Логарифмы особенно полезны, когда значения отличаются на порядки.
Например, есть суммы заказов:
5203007000120000На обычной шкале маленькие суммы почти исчезнут рядом с большими. Логарифм сжимает шкалу и помогает группировать значения по порядку величины.
Порядок величины — это примерно ответ на вопрос:
Например:
1–9— порядок0;10–99— порядок1;100–999— порядок2;1000–9999— порядок3.Для этого удобно использовать
LOG10илиLOGв PostgreSQL.Корзины по порядку величины
Допустим, нужно понять, как распределены оплаченные заказы по размеру суммы.
SELECT FLOOR(LOG(amount))::int AS magnitude, COUNT(*) AS orders_count FROM orders WHERE status = 'paid' AND amount > 0 GROUP BY FLOOR(LOG(amount))::int ORDER BY magnitude;Что делает запрос:
FLOOR.Пример результата:
01812402810313549Как это читать:
0— суммы от1до9;1— суммы от10до99;2— суммы от100до999;3— суммы от1000до9999;4— суммы от10000до99999.Это очень удобно для быстрых аналитических срезов.
Почему тут нужен FLOOR
LOG(500)не равен целому числу.Он примерно равен
2.699.Потому что
500лежит между100и1000.Чтобы превратить логарифм в номер корзины, мы берём
FLOOR.SELECT FLOOR(LOG(500)) AS magnitude;Результат:
То есть число
500попадает в корзину сотен.Подсчёт количества цифр
Ещё один полезный трюк: через логарифм можно посчитать количество цифр в положительном целом числе.
Формула такая:
Например:
7имеет1цифру;42имеет2цифры;999имеет3цифры;1000имеет4цифры.В PostgreSQL:
SELECT id, salary, FLOOR(LOG10(salary))::int + 1 AS digits_count FROM employees WHERE salary > 0 ORDER BY salary DESC;Можно использовать и
LOG(salary), потому что в PostgreSQLLOG(x)— это основание10.Но
LOG10(salary)читается яснее.SELECT id, salary, FLOOR(LOG10(salary))::int + 1 AS digits_count FROM employees WHERE salary > 0;Такой приём полезен редко, но хорошо показывает смысл логарифма: он помогает понять масштаб числа.
Логарифм для графиков
Логарифм часто используют перед построением графиков.
Например, если на графике есть значения
10,100,1000,1000000, обычная шкала может стать неудобной: маленькие значения прижмутся к нулю, а одно огромное значение растянет весь график.Логарифм делает так, что расстояния между порядками становятся равными:
10до100;100до1000;1000до10000.В SQL можно заранее подготовить значение для графика:
SELECT id, amount, LOG10(amount) AS amount_log10 FROM orders WHERE amount > 0;Потом уже строить график по
amount_log10.Важно: логарифм меняет шкалу. Это не «настоящая сумма», а преобразованное значение. В отчёте лучше явно подписывать такие колонки, чтобы читатель не перепутал.
Связь LOG и LN
LOG,LOG10иLNсчитают логарифмы, но с разными основаниями.В PostgreSQL:
SELECT LOG(100) AS log_default, LOG10(100) AS log10_value, LN(100) AS natural_log;LOG(100)иLOG10(100)дадут2.LN(100)даст примерно4.605.Почему
LNотдельно?Потому что натуральный логарифм по основанию
eчасто используется в математике, статистике, финансах и некоторых аналитических формулах.Для обычных бизнес-корзин вроде «единицы, десятки, сотни, тысячи» чаще удобнее основание
10.Как поменять основание вручную
Если в СУБД нет удобной формы
LOG(b, x), логарифм по любому основанию можно собрать через формулу смены основания:В PostgreSQL это тоже работает:
SELECT LN(8) / LN(2) AS log2_via_ln, LOG(2, 8) AS log2_builtin;Оба результата будут равны
3.То же самое можно сделать через десятичный логарифм:
SELECT LOG10(8) / LOG10(2) AS log2_via_log10;Главное — делить логарифмы, посчитанные в одном и том же основании.
LOG в разных СУБД
Вот короткая таблица, которую стоит держать под рукой.
LOG(x)илиLOG10(x)LOG10(x)log10(x)LN(x)LOG(x)илиLN(x)log(x)илиln(x)LOG(2, x)LOG2(x)илиLOG(2, x)log2(x)LOG(b, x)LOG(b, x)log(x) / log(b)Главная несовместимость:
SELECT LOG(100) AS result;В PostgreSQL это основание
10.В MySQL это основание
e.Поэтому для переносимого кода лучше писать явно:
SELECT LOG10(100) AS log10_value, LN(100) AS natural_log;Почему лучше не полагаться на умолчания
Допустим, вы написали в PostgreSQL:
SELECT LOG(amount) AS amount_log FROM orders;Вы имели в виду десятичный логарифм.
Потом этот запрос кто-то переносит в MySQL. Запрос не падает. Он продолжает работать. Но теперь
LOG(amount)означает натуральный логарифм.Это опаснее синтаксической ошибки. Синтаксическую ошибку видно сразу, а здесь отчёт может выглядеть правдоподобно, но числа будут другими.
Поэтому хороший стиль:
10писатьLOG10(x);eписатьLN(x);LOG(b, x), если СУБД это поддерживает.Так запрос легче читать и труднее сломать при переносе.
Тип результата и точность
В PostgreSQL
LOGдля числовых значений возвращает числовой результат с хорошей точностью.Например:
SELECT LOG(3) AS result;Результат будет не целым числом, потому что
3не является точной степенью10.Для большинства учебных и аналитических задач об этом достаточно знать две вещи:
Если вам нужна высокая производительность на больших объёмах и достаточно приблизительной точности, в реальных проектах иногда отдельно думают о типах данных и приведении к
double precision. Но для начинающего главное — сначала правильно понять основание и ограничения по положительным значениям.Частые ошибки
Первая ошибка — думать, что
LOG(x)везде означает одно и то же.SELECT LOG(100) AS result;В PostgreSQL результат будет
2.В MySQL результат будет примерно
4.605.Для понятного кода лучше так:
SELECT LOG10(100) AS result;Вторая ошибка — считать логарифм от нуля.
SELECT LOG(0) AS result;Такой запрос упадёт.
Лучше заранее фильтровать данные:
SELECT id, LOG10(amount) AS amount_log10 FROM orders WHERE amount > 0;Третья ошибка — защищаться только от нуля, когда в данных бывают отрицательные значения.
SELECT LOG10(NULLIF(amount, 0)) AS amount_log10 FROM orders;Если
amount = -10, проблема останется.Надёжнее так:
SELECT id, CASE WHEN amount > 0 THEN LOG10(amount) ELSE NULL END AS amount_log10 FROM orders;Четвёртая ошибка — перепутать порядок аргументов.
В PostgreSQL правильно:
SELECT LOG(2, 8) AS result;Это значит:
Результат будет
3.Пятая ошибка — забывать, что логарифм меняет смысл шкалы.
SELECT LOG10(amount) AS amount_log10 FROM orders;Это уже не сумма заказа. Это логарифм суммы. В отчёте такую колонку нужно называть явно, чтобы не вводить людей в заблуждение.
Практический пример: распределение заказов по масштабу
Допустим, у нас есть интернет-магазин. Заказы бывают маленькие, средние и очень крупные. Нужно быстро понять, в каких порядках величины живёт основная масса оплат.
SELECT FLOOR(LOG10(amount))::int AS magnitude, COUNT(*) AS orders_count, MIN(amount) AS min_amount, MAX(amount) AS max_amount FROM orders WHERE status = 'paid' AND amount > 0 GROUP BY FLOOR(LOG10(amount))::int ORDER BY magnitude;Пример результата:
012191345109921280100999322010009990481200085000Такой отчёт сразу показывает, где основная масса заказов, а где редкие крупные значения.
Для обычной группировки по диапазонам можно было бы написать
CASE WHEN. Но логарифм удобен, когда диапазоны идут по степеням десяти: десятки, сотни, тысячи, десятки тысяч.Главное
LOGв PostgreSQL считает логарифм.У него есть две основные формы:
SELECT LOG(x) AS log10_value;Это логарифм по основанию
10.SELECT LOG(b, x) AS custom_base_log;Это логарифм
xпо основаниюb.Для натурального логарифма используйте
LN.SELECT LN(x) AS natural_log;Самая важная ловушка:
LOG(x)в PostgreSQL иLOG(x)в MySQL означают разное.В PostgreSQL:
В MySQL:
Чтобы не путаться, пишите явно:
SELECT LOG10(amount) AS amount_log10, LN(amount) AS amount_ln FROM orders WHERE amount > 0;Логарифм можно считать только для положительных значений. Если в данных бывают нули или отрицательные числа, защищайте запрос через
WHERE amount > 0илиCASE.LOGполезен для лог-шкал, группировки по порядкам величины, анализа больших разбросов и подсчёта количества цифр. Но используйте его осознанно: логарифм не просто красиво форматирует число, а меняет шкалу и смысл значения.