JavaRush /Курси /SQL SELF /Функції GREATEST() і LEAST() та NULL

Функції GREATEST() і LEAST() та NULL

SQL SELF
Рівень 10 , Лекція 2
Відкрита

Сьогодні занурюємось у ще більш специфічну, але важливу тему: функції GREATEST() і LEAST(). Ти дізнаєшся, як знаходити максимальні та мінімальні значення з кількох стовпців, і, найголовніше, як NULL впливає на їхню роботу.

Якщо ти колись шукав(ла) щось найголовніше у своєму житті (кохання, роботу мрії чи найкращий рецепт піци), то одразу зрозумієш, навіщо потрібні функції GREATEST() і LEAST(). Ці функції допомагають знайти найбільше або найменше значення у списку штук. Тільки замість піци ти працюєш з числами, датами, рядками та іншими даними в PostgreSQL.

GREATEST()

GREATEST() повертає найбільше значення з переданого набору.

Синтаксис:

GREATEST(value1, value2, ..., valueN)

LEAST()

LEAST() робить навпаки: вона шукає найменше значення.

Синтаксис:

LEAST(value1, value2, ..., valueN)

Приклад:

Уявімо, що у нас є таблиця students_scores, де зберігаються оцінки студентів за три екзамени:

student_id exam_1 exam_2 exam_3
1 85 90 82
2 NULL 76 89
3 94 NULL 88

Використання GREATEST() і LEAST():

SELECT
    student_id,
    GREATEST(exam_1, exam_2, exam_3) AS highest_score,
    LEAST(exam_1, exam_2, exam_3) AS lowest_score
FROM students_scores;

Результат:

student_id highest_score lowest_score
1 90 82
2 89 NULL
3 94 NULL

Як NULL впливає на GREATEST() і LEAST()

Тепер підходимо до найцікавішого. Разом зі значеннями в таблиці можуть бути і NULL. А як ми вже знаємо, NULL — це загадкова сутність, яка означає відсутність даних або невідоме значення. Давай розберемося, що відбувається, якщо NULL потрапляє у функції GREATEST() і LEAST() в PostgreSQL.

Поведінка NULL:

У PostgreSQL функції GREATEST() і LEAST() мають особливу поведінку: вони ігнорують значення NULL при пошуку найбільшого або найменшого значення серед своїх аргументів. Важливо: Єдиний випадок, коли ці функції повернуть NULL, це якщо всі їхні аргументи є NULL.

Приклад:

SELECT
    GREATEST(10, 20, NULL, 5) AS greatest_value,
    LEAST(10, 20, NULL, 5) AS least_value;

Результат:

greatest_value least_value
20 5

Як бачиш, NULL був проігнорований, і функції повернули найбільше та найменше значення з присутніх (10, 20, 5).

А ось приклад, коли всі аргументи NULL:

Приклад:

SELECT
    GREATEST(NULL, NULL) AS greatest_nulls,
    LEAST(NULL, NULL) AS least_nulls;

Результат:

greatest_nulls least_nulls
NULL NULL

Як уникнути проблем з NULL?

Хоча PostgreSQL за замовчуванням ігнорує NULL, іноді тобі може знадобитися інша поведінка. Наприклад, якщо ти хочеш, щоб NULL розглядався як конкретне значення (наприклад, 0 або інше значення за замовчуванням) при визначенні найбільшого/найменшого. У таких випадках можна використовувати функцію COALESCE().

Функція COALESCE(arg1, arg2, ...) повертає перший не-NULL аргумент зі свого списку. Це дозволяє попередньо замінити NULL на осмислене значення перед передачею у GREATEST() або LEAST().

Приклад 1: Заміна NULL на 0

Припустимо, ми хочемо вважати, що відсутність оцінки NULL еквівалентна 0. Можемо використати COALESCE() для підстановки значення за замовчуванням.

Ось наша початкова таблиця:

student_id exam_1 exam_2 exam_3
1 90 85 82
2 NULL 89 NULL
3 NULL NULL 94

Запит:

SELECT
    student_id,
    GREATEST(
        COALESCE(exam_1, 0), 
        COALESCE(exam_2, 0), 
        COALESCE(exam_3, 0)
    ) AS highest_score,
    LEAST(
        COALESCE(exam_1, 0), 
        COALESCE(exam_2, 0), 
        COALESCE(exam_3, 0)
    ) AS lowest_score
FROM students_scores;

Результат:

student_id highest_score lowest_score
1 90 82
2 89 0
3 94 0

Приклад 2: Заміна NULL на значення з іншого стовпця

Іноді замість фіксованого значення (наприклад, 0) треба підставити значення з іншого стовпця. Наприклад, якщо exam_3 відсутній, хочемо використати значення з exam_1.

SELECT
    student_id,
    GREATEST(
        exam_1, 
        exam_2, 
        COALESCE(exam_3, exam_1)
    ) AS highest_score
FROM students_scores;

Припустимо, у нас така таблиця:

student_id exam_1 exam_2 exam_3
1 90 85 82
2 NULL 89 NULL
3 70 NULL NULL

Результат виконання запиту:

student_id highest_score
1 90
2 89
3 70

Практичні кейси

Кейс 1: Пошук максимальної знижки

order_id discount_1 discount_2 discount_3
101 5 10 7
102 NULL 3 8
103 15 NULL NULL
104 NULL NULL NULL

Ти працюєш з таблицею orders, де кожне замовлення може мати три різних типи знижки. Треба знайти максимальну з усіх знижок для кожного замовлення.

SELECT
    order_id,
    GREATEST(discount_1, discount_2, discount_3) AS max_discount
FROM orders;

Результат:

order_id max_discount
101 10
102 8
103 15
104 NULL

Кейс 2: Пошук мінімальної ціни товару

У таблиці products зберігаються ціни товарів у трьох валютах (USD, EUR, GBP). Твоє завдання — знайти мінімальну ціну для кожного товару.

product_id price_usd price_eur price_gbp
1 100 95 80
2 NULL 150 140
3 200 NULL NULL
4 NULL NULL NULL
SELECT
    product_id,
    LEAST(price_usd, price_eur, price_gbp) AS lowest_price
FROM products;
product_id lowest_price
1 80
2 140
3 200
4 NULL

Якщо всі ціни NULL, результат теж NULL

Типові помилки при використанні GREATEST() і LEAST()

Помилка 1: Неочікуваний результат через NULL.

Раніше в лекції ми детально розібрали, як NULL впливає на GREATEST() і LEAST() в PostgreSQL. Основна помилка полягає в тому, що користувачі, звиклі до поведінки NULL в інших СУБД (де один NULL "отруює" весь результат), очікують такого ж і від PostgreSQL.

Як проявляється помилка: Ти можеш помилково думати, що якщо у списку аргументів є NULL, функція завжди поверне NULL. В результаті, можеш без потреби застосовувати COALESCE() до всіх аргументів, що може ускладнити запит і сповільнити його виконання, якщо у твоєму сценарії NULL має бути просто проігнорований.

Помилка 2: Використання GREATEST() і LEAST() з несумісними типами.

Функції GREATEST() і LEAST() призначені для порівняння значень одного і того ж типу даних або типів, які можуть бути неявно приведені один до одного. Спроба порівняти значення зовсім різних, несумісних типів, призведе до помилки.

Як проявляється помилка: Ти отримаєш повідомлення про помилку, яке вказує на несумісність типів даних.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ