Функция IIF в T-SQL позволяет быстро и просто добавлять логику if-else в SQL запросы. Давайте разберемся как она работает и где можно ее применить на практических примерах.
Описание и синтаксис IIF функции
Функция IIF появилась в SQL Server 2012 как сокращенный способ написания выражений CASE для добавления условной логики в запросы. Она принимает три параметра:
- Логическое выражение
- Значение, если выражение истинно
- Значение, если выражение ложно
Синтаксис выглядит следующим образом:
IIF(boolean_expression, true_value, false_value)
Например, чтобы вернуть 'Высокий' или 'Низкий' в зависимости от значения переменной @score, можно написать:
DECLARE @score INT = 90; SELECT IIF(@score > 80, 'Высокий', 'Низкий');
Это полностью эквивалентно более длинной конструкции CASE:
DECLARE @score INT = 90; SELECT CASE WHEN @score > 80 THEN 'Высокий' ELSE 'Низкий' END;
К IIF применяются те же правила обработки NULL значений и определения возвращаемого типа данных, что и для CASE. Также IIF можно вкладывать друг в друга не более 10 раз, аналогично ограничению на вложенность CASE.
Примеры использования IIF в запросах
Рассмотрим несколько практических случаев применения функции IIF в T-SQL запросах.
Добавим условие в оператор SELECT для выборки разных столбцов в зависимости от значения переменной:
DECLARE @parameter VARCHAR(10) = 'type'; SELECT IIF(@parameter = 'name', first_name, IIF(@parameter = 'type', customer_type, 'Not found')) FROM customers;
Изменим данные с помощью IIF при обновлении таблицы:
UPDATE products SET status = IIF(units_in_stock = 0, 'Out of stock', status);
Заменим NULL значения в столбце на другие значения:
SELECT order_id, IIF(ship_date IS NULL, 'Not shipped', CONVERT(VARCHAR(10), ship_date)) AS ship_date FROM orders;
Это лишь несколько начальных примеров использования IIF, которые показывают гибкость и универсальность этой функции для решения разных задач.
Далее мы рассмотрим более сложные случаи применения IIF с другими функциями, для обработки ошибок, оптимизации запросов и решения бизнес-задач.
Одна из сильных сторон IIF - это возможность комбинировать ее с другими функциями T-SQL. Рассмотрим несколько примеров.
С SUM
Чтобы посчитать сумму значений столбца только для определенных строк, можно использовать конструкцию:
SELECT SUM(IIF(year = 2022, revenue, 0)) AS revenue_2022, SUM(IIF(year = 2023, revenue, 0)) AS revenue_2023 FROM sales;
С COALESCE
Функция COALESCE возвращает первое не NULL значение из списка. Совместно с IIF это позволяет гибко работать с отсутствующими данными:
SELECT order_id, COALESCE(shipped_date, IIF(shipped_date IS NULL, estimated_ship_date, NULL)) AS ship_date FROM orders;
С CAST и CONVERT
Можно комбинировать IIF с функциями преобразования типов данных CAST и CONVERT, чтобы возвращать значения в нужном формате:
SELECT order_id, IIF(CAST(shipped_date AS DATE) = CAST(GETDATE() AS DATE), 'Shipped today', CONVERT(VARCHAR(10), shipped_date, 101) ) AS shipment FROM orders;
Обработка ошибок с помощью IIF
Распространенное применение IIF - это обработка различных ошибок и исключений в запросах SQL. Рассмотрим конкретные случаи.
Деление на ноль
Чтобы избежать ошибки деления на ноль в вычислениях, можно написать:
SELECT order_id, IIF(units IS NULL OR units = 0, NULL, total / units) AS average FROM orders;
Превышение ограничения по длине
Если результат выражения превышает максимально допустимый размер для данного типа, IIF позволяет вернуть усеченное значение:
SELECT name, IIF(LEN(description) > 50, LEFT(description, 50) + '...', description) AS description FROM products;
Применение IIF для оптимизации запросов
IIF может использоваться не только для добавления логики в запросы SQL, но и для оптимизации их производительности. Конкретные приемы будут рассмотрены далее.
Фильтрация данных на стороне сервера
Вместо фильтрации строк на клиентской стороне, вы можете использовать IIF в предложении WHERE для фильтрации непосредственно на сервере:
SELECT * FROM products WHERE IIF(category_id = 1, price > 100, price > 50);
Это позволит отправить на клиента уже отфильтрованный набор данных, сократив объем передаваемой информации.
Исключение дорогостоящих операций
Допустим, в запросе присутствует вызов внешней процедуры, который требует много времени. С помощью IIF можно исключить его выполнение для части данных:
SELECT *, IIF(created_date > '20210101', expensive_udf(id), NULL) AS extended_data FROM orders WHERE user_id = @id;
Переключение соединений
В некоторых случаях имеет смысл использовать разные типы соединений в одном запросе, например внешнее и внутреннее. Это можно реализовать через CASE или IIF:
SELECT * FROM table1 LEFT JOIN table2 ON table1.id = table2.id AND IIF(table1.date < '20220101', 1, 0) = 1
Сравнение IIF и CASE
Несмотря на идентичность работы IIF и CASE, между ними есть некоторые отличия:
- Синтаксис IIF проще и компактнее
- CASE читается и воспринимается нагляднее
- IIF быстрее компилируется, CASE может выполняться эффективнее