Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Регистрируясь, я даю согласие на обработку данных и условия почтовых рассылок.
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр Погрузись в удивительный мир настоящей рыбалки! Лови живую рыбу в естественных водоёмах, открой для себя новые рыбные места и поймай свой долгожданный трофей!

Реальная Рыбалка

Симуляторы, Мультиплеер, Спорт

Играть

Топ прошлой недели

  • solenakrivetka solenakrivetka 7 постов
  • Animalrescueed Animalrescueed 53 поста
  • ia.panorama ia.panorama 12 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая «Подписаться», я даю согласие на обработку данных и условия почтовых рассылок.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
0 просмотренных постов скрыто
3
viperinthebath
viperinthebath

Продолжение поста «Нужен совет по LibreOffice Base (SQL в том числе)»⁠⁠1

4 дня назад

Итак, решение найдено с помощью очень хорошего и талантливого человека, который тоже есть на Пикабу, но свело нас не Пикабу, а творчество. Огромное спасибо ей и за решение, и за творчество! Как и обещал ранее, публикую решение тут, вдруг кому пригодится. Запрос написан очень красиво и понятно, легко разобраться. ИМХО по таким примерам очень удобно изучать SQL. Да и @Avenir.Sirgun хотел взглянуть)))
Итак, вот запрос, который решает:

SELECT

YEAR(R.ДатаРасход) AS Год,

MONTH(R.ДатаРасход) AS Месяц,

A.Адрес,

M.НазваниеМатериал,

SUM(R.КолвоМатериала) AS Количество

FROM Расходы AS R

JOIN Работы AS W ON R.IDРабот = W.IDРабот

JOIN Адреса AS A ON W.IDАдреса = A.IDАдрес

JOIN Материалы AS M ON R.IDМатериала = M.IDМатериал

GROUP BY

YEAR(R.ДатаРасход),

MONTH(R.ДатаРасход),

A.Адрес,

M.НазваниеМатериал

ORDER BY

Год,

Месяц,

A.Адрес,

M.НазваниеМатериал;

Структура БД есть в изначальном посте.
Далее уже можно модифицировать, если надо.
Задача решена! Ура! Ещё раз огромное спасибо, В..., ты очень мне помогла! (не тегаю, т.к. не получал на то дозволения)

Показать полностью
[моё] Libreoffice База данных SQL Программирование Base IT Решение проблемы Ответ на пост Текст
0
3
viperinthebath
viperinthebath

Нужен совет по LibreOffice Base (SQL в том числе)⁠⁠1

8 дней назад

Друзья, задумал немного помочь себе и упростить работу. В свободное время решил соорудить базу данных выполненных работ по участку и потраченных на это материалов. Когда-то успешно делал себе "помогалки" в MS Access (в 90ых ещё), поэтому выбрал LibreOffice Base. Структура вот такая:

Таблицы БД со связями

Таблицы БД со связями

Форму для заполнения сделал. Заполняется, хранит данные. Отчёт по всем тратам отдельно создать - не проблема, получилось. Это без условий и без формул, просто списком.
Но никак не могу осилить отчёт, в котором бы выдавалась сумма по каждому адресу - сколько потрачено каждого вида материала. Типа,
Май:
Адрес1:
материал1 - 1
материал2 -3
Адрес2:
материал1 - 2
материал3 -4


Гуглил-яндексил, пытался по наитию, ничего не получается. Наверное, если просижу пару недель, изучая всё к ряду, то осилю... но подсказка бы ускорила.
Конечно, без рейтинга. Не знал, в какое сообщество отправить, но, надеюсь, не ошибся, ибо запрос-то на SQL писать придётся))) - долго ждать модерации, публикую без сообщества.
Заранее благодарен!
(Есть и второй вопрос - никак не могу придумать, как сделать типовые работы - чтобы кнопочку нажал, и автоматически заполнились поля формы, создались записи в таблице с расходами материалов)

Показать полностью 1
Libreoffice База данных SQL Без рейтинга
25
4
VelStyling
VelStyling
Серия SQL: знакомство

Условные выражения в запросах⁠⁠

27 дней назад

CASE WHEN - часто используемое условное выражение в запросах. Его особенности и факты далее.

Условные выражения в запросах

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

CASE - возвращает значение, но не управляет логикой выполнения запроса.

SELECT

name,

CASE

WHEN salary > 100000 THEN 'богач'

WHEN salary BETWEEN 50000 AND 100000 THEN 'норм'

ELSE 'бедняк'

END AS category

FROM employees;

Здесь CASE не «делает выборку», а вычисляет новое значение для каждой строки.

Где используется CASE

✅ В SELECT - чтобы выводить вычисленные поля
✅ В WHERE - чтобы сделать фильтрацию условной
✅ В ORDER BY - чтобы сортировать по кастомной логике
✅ В GROUP BY и HAVING - для агрегатов с условиями

Пример в ORDER BY:

ORDER BY

CASE WHEN status = 'vip' THEN 1 ELSE 2 END

В итоге VIP-клиенты окажутся первыми — без лишнего UNION или сортировки по тексту.

Где нельзя использовать CASE

  • Нельзя динамически подменять им названия колонок или таблиц — SQL так не работает:

SELECT * FROM CASE WHEN ... THEN table1 ELSE table2 END -- ошибка

  • Нельзя изменять структуру запроса — CASE не может выбирать, какие поля попадут в SELECT.

То есть он работает только на уровне данных, не на уровне схемы запроса.

Неочевидные факты

1. CASE возвращает первое совпадение

SQL идёт сверху вниз — как только условие совпало, остальные даже не проверяются.
Поэтому важно порядок условий.

CASE

WHEN score > 80 THEN 'A'

WHEN score > 90 THEN 'A+' -- никогда не сработает

END

Потому что >80 ловит всё, включая >90.

2. Тип результата — общий для всех веток

CASE пытается привести все результаты к единому типу.
Если ты вернёшь 'текст' и NULL, всё ок.
Но если 'текст' и 123, то SQL может выдать ошибку или привести число к строке.
💡 Всегда делай значения одного типа, особенно если потом используешь CASE в арифметике.

3. Есть две формы: сравнительная и поисковая

Обычно используют поисковую:

CASE WHEN condition THEN result ... END

Но есть ещё сравнительная:

CASE status

WHEN 'new' THEN 1

WHEN 'active' THEN 2

END

Она короче, но менее гибкая — работает только с равенством (=).

4. CASE + агрегаты = мощный аналитический трюк

Чтобы посчитать агрегаты по категориям в одной строке:

SELECT

SUM(CASE WHEN gender = 'M' THEN 1 ELSE 0 END) AS male_count,

SUM(CASE WHEN gender = 'F' THEN 1 ELSE 0 END) AS female_count

FROM users;

Один запрос, два счётчика, без подзапросов и джойнов.

5. CASE в WHERE — не всегда оптимален

Когда ты используешь CASE в WHERE, PostgreSQL часто не может применить индекс,
потому что условие становится непредсказуемым.

Пример:

WHERE

CASE WHEN is_vip THEN discount > 10 ELSE discount > 30 END

Лучше выносить логику в OR:

WHERE (is_vip AND discount > 10)

OR (NOT is_vip AND discount > 30)

Так планировщик сможет использовать индексы (их наличие подразумевается)

Где CASE особенно полезен

  • Когда нужно сделать динамическую сегментацию данных (категории, статусы, группы)

  • При построении витрин и отчётов (разделить аудиторию, выделить группы риска и т.п.)

  • Для чистки данных на лету (заменить NULL на текст или дефолтное значение)

  • В AB-тестах — присвоить группе метку на основании условия

Если тебе нравятся такие разборы SQL с реальными примерами и подводными камнями —
подписывайся на мой Telegram На связи: SQL

Показать полностью 1
[моё] SQL Microsoft Excel Аналитика Аналитик Анализ данных Самообразование Длиннопост
14
2
user5236465

Небольшой тренинг по XML в PostgreSQL на примере производственного календаря⁠⁠

1 месяц назад

Новый Год уже скоро, а значит нужен свежий производственный календарь в базе данных PostgreSQL. Но как совершенно обленившийся IT-шник, заводить его руками не хочется. Хочется, чтобы вызовом одной функции он сразу появился. Ну а уж из этой функции можно его сохранить в табличку и спокойно использовать до следующего Нового Года. А тогда опять просто вызвать функцию и с чистой совестью отрапортовать о выполненной работе. Моя цель - показать возможности COPY ... FROM PROGRAM и простейшие приемы парсинга XML в PostgreSQL.

Для начала пришлось поискать, где же его взять в наиболее удобном для обработки виде. Нашел!

Ставить какие-либо расширения на PostgreSQL не хотелось, поэтому ограничился прямым вызовом wget через COPY. Для этого сначала создаем временную таблицу:

DROP TABLE IF EXISTS tmp_tmp;
CREATE TEMP TABLE tmp_tmp (
  ID serial PRIMARY KEY,
  res text NOT NULL);

ID нам нужен исключительно для сохранения порядка строк, полученных от wget. Теперь мы вполне можем заполнить эту табличку и даже посмотреть на результат:

COPY tmp_tmp (res) FROM PROGRAM
  '/usr/bin/wget -qO - https://xmlcalendar.ru/data/ru/2026/calendar.xml'
  WITH (FORMAT text);
SELECT res FROM tmp_tmp ORDER BY ID;

Теперь нам нужно из полученных текстовых строк получить XML

SELECT string_agg(res,'' ORDER BY ID)::xml AS res
FROM tmp_tmp

Для проверки при помощи xmltable() распарсим заголовочную строку вида <calendar year="2026" lang="ru" date="2025.09.30" country="ru">, содержащую год, страну, для которой этот календарь, и дату его последнего изменения.

WITH CTE AS (
  SELECT string_agg(res,'' ORDER BY ID)::xml AS res
  FROM tmp_tmp ),
CheckYear AS (
  SELECT Y.for_year, Y.for_country, Y.create_date
  FROM CTE C
  CROSS JOIN xmltable('//calendar' PASSING C.res COLUMNS
    for_year smallint PATH '@year',
    for_country varchar PATH '@Country',
    create_date date PATH '@DaTe') Y
  WHERE Y.for_year=2026::smallint )
SELECT * FROM CheckYear

В дальнейшем я буду просто использовать имена общих табличных выражений, которые уже показал, не повторяя их код.

Теперь распарсим таблицу праздников. Она содержит только внутренний числовой идентификатор праздника и его полное наименование в строках вида <holiday id="6" title="День Победы"/>

WITH [...]
Holidays AS (
  SELECT H.id, H.title
  FROM CheckYear Y
  CROSS JOIN CTE C
  CROSS JOIN xmltable('//calendar/holidays/holiday' PASSING C.res COLUMNS
    id smallint PATH '@id',
    title varchar PATH '@title') H )
SELECT * FROM Holidays;

Затем распарсим основную часть, содержащую строки вида <day d="03.08" t="1" h="4"/> или <day d="04.29" t="1" f="04.27"/>. Тут требуются пояснения. Под тегом d скрывается дата в формате ММ.ДД. Тег t определяет тип записи: 1 - выходной день, 2 - рабочий и сокращенный (может быть использован для любого дня недели), 3 - рабочий день (суббота/воскресенье). Тег h является ссылкой на идентификатор праздника из предыдущего запроса. А тег f - дата с которой был перенесен выходной день тоже в формате ММ.ДД. При этом суббота и воскресенье считаются выходными, если нет тегов day с атрибутом t=2 и t=3 за этот день.

WITH [...]
SpecialDays AS (
  SELECT ('2026-'
    ||left(D.d,2)||'-'
    ||right(D.d,2))::date AS special_date,
  CASE WHEN D.t=1 THEN 'Holiday'
    WHEN D.t=2 THEN 'Shortened'
    WHEN D.t=3 THEN 'Working'
    ELSE NULL END AS day_type,
  ('2026-'
    ||left(D.f,2)||'-'
    ||right(D.f,2))::date AS from_date,
    H.title AS holiday_name
  FROM CheckYear Y
  CROSS JOIN CTE C
  CROSS JOIN xmltable('//calendar/days/day' PASSING C.res COLUMNS
    d varchar(5) PATH '@d',
    t smallint PATH '@t',
    h smallint PATH '@h',
    f varchar(5) PATH '@f') D
  LEFT JOIN Holidays H ON H.id=D.h )
SELECT * FROM SpecialDays;

Для наглядности я заменил числовые типы на краткое их строковое описание. Даты же из формата MM.ДД преобразовал в формат ISO ГГГГ-ММ-ДД, а затем уже в тип date.

Теперь осталось только сгенерировать календарь за год и для каждого дня указать количество рабочих часов для 40-часовой рабочей недели.

SELECT C.d::date AS pk_date,
  CASE WHEN S.day_type='Shortened' THEN 7
    WHEN S.day_type='Working' THEN 8
    WHEN S.day_type='Holiday' THEN 0
    WHEN extract(DOW FROM C.d) IN (0,6) THEN 0
    ELSE 8 END::smallint AS working_hours,
  S.from_date, S.holiday_name
FROM generate_series(('2026-01-01')::timestamp,
  ('2026-12-31')::timestamp,
   '1 day'::interval) C(d)
LEFT JOIN SpecialDays S ON S.special_date=C.d;

Сокращенные предпраздничные дни получили по 7 часов. Рабочие дни в выходные - 8. Праздники - 0. Воскресенье и суббота (в PostgreSQL нулевой и шестой дни недели соответственно) - 0. Ну а остальные дни считаются рабочими по 8 часов.

После всего этого осталось только создать функцию

CREATE OR REPLACE FUNCTION get_working_calendar(
  calendar_year smallint,
  calendar_lang varchar(2)='ru')
RETURNS TABLE (
  pk_date date,
  working_house smallint,
  from_date date,
  holiday_name varchar
) AS $function$
<<func>>
DECLARE
  sql_cmd varchar='COPY tmp_tmp (res) FROM PROGRAM $$'
    ||$$/usr/bin/wget -qO - https://xmlcalendar.ru/data/$$
    ||calendar_lang||$$/$$
    ||calendar_year::text
    ||$$/calendar.xml --no-check-certificate$$
    ||'$$ WITH (FORMAT text);';
BEGIN
DROP TABLE IF EXISTS tmp_tmp;
CREATE TEMP TABLE tmp_tmp (
  ID serial PRIMARY KEY,
  res text NOT NULL);
EXECUTE func.sql_cmd;

RETURN QUERY WITH CTE AS (
  SELECT string_agg(res,'' ORDER BY ID)::xml AS res
  FROM tmp_tmp ),
CheckYear AS (
  SELECT Y.for_year, Y.for_country, Y.create_date
  FROM CTE C
  CROSS JOIN xmltable('//calendar' PASSING C.res COLUMNS
    for_year smallint PATH '@year',
    for_country varchar PATH '@country,
    create_date date PATH '@date') Y
  WHERE Y.for_year=calendar_year ),
Holidays AS (
  SELECT H.id, H.title
  FROM CheckYear Y
  CROSS JOIN CTE C
  CROSS JOIN xmltable('//calendar/holidays/holiday'
    PASSING C.res COLUMNS
    id smallint PATH '@id',
    title varchar PATH '@title') H ),
SpecialDays AS (
  SELECT (calendar_year::text||'-'
    ||left(D.d,2)||'-'
    ||right(D.d,2))::date AS special_date,
  CASE WHEN D.t=1 THEN 'Holiday'
    WHEN D.t=2 THEN 'Shortened'
    WHEN D.t=3 THEN 'Working'
    ELSE NULL END AS day_type,
    (calendar_year::text||'-'
      ||left(D.f,2)||'-'
      ||right(D.f,2))::date AS from_date,
    H.title AS holiday_name
  FROM CheckYear Y
  CROSS JOIN CTE C
  CROSS JOIN xmltable('//calendar/days/day' PASSING C.res COLUMNS
    d varchar(5) PATH '@d',
    t smallint PATH '@t',
    h smallint PATH '@h',
    f varchar(5) PATH '@f') D
  LEFT JOIN Holidays H ON H.id=D.h )
SELECT C.d::date AS pk_date,
  CASE WHEN S.day_type='Shortened' THEN 7
    WHEN S.day_type='Working' THEN 8
    WHEN S.day_type='Holiday' THEN 0
    WHEN extract(DOW FROM C.d) IN (0,6) THEN 0
    ELSE 8 END::smallint AS working_hours,
  S.from_date, S.holiday_name
FROM CheckYear Y
CROSS JOIN generate_series((calendar_year::text||'-01-01')::timestamp,
    (calendar_year::text||'-12-31')::timestamp,
    '1 day'::interval) C(d)
LEFT JOIN SpecialDays S ON S.special_date=C.d;
END; $function$ LANGUAGE plpgsql;

И убедиться, что производственный календарь успешно загружается и парсится:

SELECT * FROM get_working_calendar(2024::smallint);

P.S. Забыл указать, что доступны производственные календари с 2015 года для России (ru) Белоруссии (by), Украины (ua), Казахстана (kz) и Узбекистана (uz)

P.P.S. Простите, если что, но после совершенно убогих постов про SQL, захотелось написать пост имеющий хоть ничтожную практическую ценность.

Показать полностью
SQL Postgresql Xml Текст Длиннопост
22
3
VelStyling
VelStyling
Серия SQL: знакомство

Неочевидные факты про MIN и MAX⁠⁠

1 месяц назад

Простые функции. Кажется, что они находят просто минимум и максимум. Но есть и особенность их использования для интерпретации результатов. Об этом далее.

Неочевидные факты про MIN и MAX

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

MIN и MAX — не только про числа

Они работают с любыми типами данных:

  • датами (MIN(date) даст самую раннюю дату),

  • строками (MAX(name) вернёт последнюю в алфавитном порядке),

  • булевыми значениями (MIN(bool) — false, MAX(bool) — true).

Иногда этим можно ловко воспользоваться — например, чтобы узнать, есть ли хоть один true:

SELECT MAX(is_active) FROM users;

Если вернёт true — значит, кто-то активен. Красиво и лаконично.

MIN и MAX — не только агрегатные, но и оконные функции

Можно получить минимум или максимум в рамках окна, не теряя детализацию:

SELECT

user_id,

date,

MAX(date) OVER (PARTITION BY user_id) AS last_activity

FROM logins;

Так можно легко вытащить, когда пользователь последний раз заходил — без группировки и без JOIN.

MIN/MAX и NULL

Они игнорируют NULL.
То есть если у тебя все значения NULL, то результат — NULL.
Это часто ломает аналитику, особенно при сравнении с COALESCE или при объединении данных.

SELECT MAX(COALESCE(score, 0)) -- вернёт 0, а не NULL

→ Иногда важно явно заменить NULL, чтобы не получить "пустой" результат.

MIN/MAX могут ускорить выборку

Если в таблице есть индекс по нужному полю —
MIN() и MAX() используют только крайний элемент индекса.
Это значит, что:

SELECT MAX(price) FROM products;

может пройтись не по миллиону строк, а просто взять последнее значение из B-tree индекса.
То есть — мгновенно.

Можно найти строку с минимальным/максимальным значением

Классическая боль аналитика: как вытащить не просто максимум, а всю строку, где он встретился.

💡 Один из лучших способов — оконная функция + фильтр:

SELECT *

FROM (

SELECT *,

ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn

FROM employees

) t

WHERE rn = 1;

→ Получаем сотрудника с максимальной зарплатой.
Без подзапросов, без JOIN, без боли.

Неочевидный кейс: поиск экстремумов в группах

SELECT department, MIN(salary), MAX(salary)

FROM employees

GROUP BY department;

Классика, но важно:
разница между MAX и MIN = разброс значений, полезный показатель в аналитике (например, зарплат).

💬 Если хочешь больше таких разборов с реальными кейсами SQL без воды — подписывайся на мой Telegram 👉На связи: SQL
Там я рассказываю про SQL так, чтобы стало интересно даже тем, кто раньше его ненавидел 😄

Показать полностью 1
[моё] SQL Аналитика Аналитик База данных Microsoft Excel Анализ данных Min Саморазвитие Эмоциональное выгорание Длиннопост
4
15
Slava.Rozhnev
Slava.Rozhnev
Серия SQLize.online

SQL-кодеры, приготовиться! Онлайн-песочница sqlize.online получила большие обновления (и свежую Oracle 26ai)⁠⁠

1 месяц назад

Привет, Пикабу! На связи Слава Рожнев, который все ещё делает sqlize.online — ту самую удобную онлайн-песочницу, где можно быстро проверить SQL-запрос, не устанавливая тяжеловесные СУБД.

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

💾 Больше не нужно копировать в блокнот: Сохраняем код!

Раньше было как? Написал ты, например, сложный CUBE или крутую оконную функцию, чтобы решить задачу, получил результат, закрыл вкладку — и всё, код улетел в Лету.

Теперь это в прошлом! Я добавил регистрацию на платформе. и возможность для всех зарегистрированных пользователей сохранять свои примеры кода!

Это прямо must-have, если вы:

* Решаете задачки и хотите вернуться к ним позже.

* Собираете личные «шпаргалки» для работы с разными диалектами SQL.

* Просто не хотите потерять гениальный запрос, который родился в 3 часа ночи.

Теперь ваши наработки хранятся в личном кабинете. Пользуйтесь на здоровье!

🚀 Oracle 26ai: Выходим на новый уровень

А вот это вишенка на торте для фанатов энтерпрайзных баз данных: мы обновили версию Oracle до самой последней — 26ai!

Да-да, с прицелом на искусственный интеллект. Теперь вы можете тестировать свои запросы на самой свежей и навороченной версии, которая включает массу новых фич, улучшенную производительность и, конечно, все те возможности, которые Oracle предлагает в области работы с ИИ и аналитикой.

Что это значит для вас:

* Вы работаете с самым актуальным инструментарием.

* Можно заранее проверить, как будут работать ваши запросы в самой современной продакшн-среде.

* Прощайте, устаревшие синтаксические конструкции, привет, новые возможности!

Итого:

* Регистрация: Готово!

* Сохранение кода: Готово!

* Oracle 26ai: Готово!

Заходите, регистрируйтесь, сохраняйте свои мега-запросы и ломайте нашу новую Oracle 26ai (в пределах разумного, конечно). Жду ваших багрепортов и предложений в комментариях.

Всем удачи в кодинге и да пребудет с вами долгожданный QUALIFY!

Наш девиз: «Надо тестить? Заходи, инсталляция не нужна!»

Показать полностью
[моё] Программирование IT Обучение SQL Oracle База данных Песочница Текст
3
4
VelStyling
VelStyling
Серия SQL: знакомство

AVG. Почему "среднее" не всегда среднее⁠⁠

1 месяц назад

Когда мы видим AVG, кажется, всё просто:

Возьми все значения и найди среднее арифметическое.

Но на практике AVG часто ведёт себя не так, как ты ожидаешь — и это причина десятков аналитических факапов в отчётах.

AVG. Почему &quot;среднее&quot; не всегда среднее

А пока подписывайся на мой каналНа связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

Что делает AVG()?

AVG() - агрегатная функция. Она считает среднее значение по всем строкам, которые попали в выборку после фильтрации WHERE

SELECT AVG(column_name)

FROM table_name

WHERE condition;

Пример:

| id | salary |
| -- | ------ |
| 1 | 1000 |
| 2 | 2000 |
| 3 | NULL |
| 4 | 3000 |

SELECT AVG(salary) FROM employees;

Результат → 2000

❗ Почему не (1000 + 2000 + 0 + 3000) / 4 = 1500?

Потому что AVG игнорирует NULL.
Он считает (1000 + 2000 + 3000) / 3.

Если тебе нужно учесть “отсутствие зарплаты” как ноль —
надо явно это сказать базе:

SELECT AVG(COALESCE(salary, 0)) FROM employees;

Где используется AVG

AVG() — базовый инструмент в аналитике:

  • 📈 средний чек (AVG(order_amount))

  • 💰 средняя зарплата по отделу

  • 🕒 среднее время выполнения заказа

  • ⭐ средний рейтинг продукта

Но это только верхушка айсберга.
Ниже — интересные кейсы, где AVG используется неочевидно, но мощно 👇

Обычный AVG считает всё одинаково,
но в реальном мире “вес” данных может быть разный.

Пример — средняя оценка курса:

| user_id | rating | reviews |
| ------- | ------ | ------- |
| 1 | 5 | 1 |
| 2 | 4 | 20 |

Если ты просто возьмёшь AVG(rating) → 4.5
Но по факту второй пользователь оставил 20 отзывов, его мнение должно весить больше:

SELECT SUM(rating * reviews) / SUM(reviews) AS weighted_avg

FROM ratings;

Вот это уже взвешенное среднее, и результат будет ближе к 4.

AVG не коммутативен в агрегациях

AVG(AVG(...)) ≠ AVG(...)

Пример:

| group | value |

| ----- | ----- |

| A | 10 |

| A | 20 |

| B | 100 |

| B | 100 |

| B | 100 |

SELECT AVG(avg_val) FROM (

SELECT group, AVG(value) AS avg_val

FROM t GROUP BY group

) s;

Результат будет → 57.5
А реальное среднее по всей таблице = 86.

Почему?
Потому что при втором AVG каждая группа имеет одинаковый “вес”,
а не количество строк. Это типичный аналитический капкан.

AVG в окнах (window functions)

AVG() можно использовать по “скользящему окну”, чтобы считать динамику:

SELECT

date,

AVG(price) OVER (ORDER BY date ROWS 6 PRECEDING) AS moving_avg_7d

FROM stock_prices;

👉 Это 7-дневное скользящее среднее — классика анализа временных рядов, трейдинга и предсказания трендов.

Среднее как критерий “нормальности”

В аналитике AVG часто используют вместе со STDDEV:

STDDEV (Standard Deviation) — стандартное отклонение (среднеквадратичное отклонение). Это статистическая мера разброса данных относительно их среднего значения в определённом периоде.

SELECT *

FROM purchases

WHERE amount > AVG(amount) + 3 * STDDEV(amount);

Так находят аномально большие значения — подозрительные платежи, мошеннические операции и т.д.

AVG по датам — это тоже работает

Мало кто знает, что AVG() можно применять даже к датам:

SELECT AVG(order_date)::date FROM orders;

PostgreSQL переведёт даты во внутренние числа и вычислит “среднюю дату” —
по сути, середину временного диапазона.
Это удобно, если хочешь понять, когда чаще всего происходили события.

AVG и производительность

AVG() всегда вычисляется через SUM и COUNT,
поэтому если ты делаешь:

SELECT COUNT(*), SUM(amount), AVG(amount)

— оптимизатор посчитает всё за один проход по данным.
Но если AVG в отдельном запросе — будет второй проход.
Мелочь, а при миллионах строк чувствуется.

Мой канал На связи: SQL ждет тебя, если ты тоже хочешь познакомиться с базовым языком для аналитики данных.

Подписывайся!

Показать полностью 1
[моё] Аналитик Аналитика Отчетность Microsoft Excel SQL База данных Длиннопост
0
11
IliaHohlov
IliaHohlov
Лига программистов

Собеседование по SQL: 4 способа подсчитать количество определённой буквы в слове⁠⁠

1 месяц назад

Нужно решить задачу на собеседовании разными способами: посчитать сколько раз встречается определённая буква в слове или фразе.

Способ 1: Узнать на сколько символов уменьшится длина слова, если функцией REPLACE удалить все вхождения этой буквы из него:

Это и другие решения будут на примере СУБД ORACLE. На самом деле способов решения подобных задач куда больше, но пока ограничимся четырьмя.

Способ 2: Представить слово как таблицу из одного столбца из его букв, и функцией COUNT подсчитать количество нужной буквы. Вначале напишем запрос, который делал бы таблицу из букв слова:

Теперь напишем SELECT из этой полученной таблицы. Подсчитаем сколько строчек с нужной буквой:

Способ 3: Развернуть слово из строки в столбец по аналогии с предыдущим решением, и с помощью PIVOT подсчитать количество строк с нужной буквой:

Можно даже подсчитать количество вхождений каждой буквы из которых состоит слово или фраза:

Способ 4: Использовать регулярные выражения:

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

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

Буду рад лайку, если понравилась статья! И заходи на мой Телеграм канал. Сюда регулярно выкладываю новые задачи с собеседований по SQL и решаем реальные практические задачи!

Показать полностью 6
Программирование IT Тестирование Собеседование SQL Oracle Программист Telegram (ссылка) Длиннопост
1
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Маркет Промокоды Пятерочка Промокоды Aroma Butik Промокоды Яндекс Путешествия Промокоды Яндекс Еда Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии