Как правильно создать приписку с учетом склонения слов в PostgreSQL?

У меня есть число, которое может меняться в диапазоне от 0 до 600. <br/> 
Мне нужно добавить к каждому числу слово "Автомобиль", при этом склоняя его в зависимости от значения числа: <br/> - 0 автомобилей <br/> - 1 автомобиль <br/> - 2 автомобиля и так далее. <br/> Поскольку диапазон чисел очень большой, использование конструкции <b>case</b> не будет эффективным. Я не смог найти подходящую функцию для этой задачи в интернете. <br/> Можете помочь мне, добрые люди?
  • 5 сентября 2024 г. 12:22
Ответы на вопрос 4
В PostgreSQL нет встроенной функции, которая автоматически склоняет существительные в зависимости от числа, как вы описали. Однако, вы можете создать свою собственную функцию на PL/pgSQL, которая будет выполнять эту задачу. 

Приведу пример такой функции, которая будет принимать целое число и возвращать соответствующую строку с правильно склонённым словом "автомобиль":

```sql
CREATE OR REPLACE FUNCTION get_car_word(count INTEGER) 
RETURNS TEXT AS $$
BEGIN
    IF count = 1 THEN
        RETURN count || ' автомобиль';
    ELSIF count % 10 = 1 AND count % 100 <> 11 THEN
        RETURN count || ' автомобиль';
    ELSIF (count % 10 >= 2 AND count % 10 <= 4) AND (count % 100 < 12 OR count % 100 > 14) THEN
        RETURN count || ' автомобиля';
    ELSE
        RETURN count || ' автомобилей';
    END IF;
END;
$$ LANGUAGE plpgsql;
```

### Как это работает:
1. Если `count` равно 1, возвращаем "1 автомобиль".
2. Если число оканчивается на 1, но не на 11, возвращаем "X автомобиль".
3. Если число оканчивается на 2, 3 или 4 (но не на 12, 13 или 14), возвращаем "X автомобиля".
4. Во всех остальных случаях возвращаем "X автомобилей".

### Пример использования:
Теперь вы можете использовать функцию `get_car_word(count)` для получения правильного склонения:

```sql
SELECT get_car_word(0);  -- 0 автомобилей
SELECT get_car_word(1);  -- 1 автомобиль
SELECT get_car_word(2);  -- 2 автомобиля
SELECT get_car_word(5);  -- 5 автомобилей
SELECT get_car_word(11); -- 11 автомобилей
SELECT get_car_word(21); -- 21 автомобиль
SELECT get_car_word(22); -- 22 автомобиля
SELECT get_car_word(25); -- 25 автомобилей
```

Таким образом, вы сможете динамически генерировать строки с правильной формой слова "автомобиль" в зависимости от числа.
SELECT amount || ' ' ||
       CASE WHEN amount % 100 / 10 = 1 THEN 'автомобилей'
            WHEN amount % 10 = 1 THEN 'автомобиль'
            WHEN amount % 10 IN (2,3,4) THEN 'автомобиля'
            ELSE 'автомобилей'
            END
FROM generate_series(0,600) AS source (amount)

fiddle
Если вы внимательно посмотрите на окончания, то поймёте, что они поддаются описанию довольно простым повторяющимся паттерном (особенно начиная со второго десятка).
если (n % 100 >= 10 && n % 100 <= 19) || n % 10 == 0 || n % 10 >= 5 то
  "автомобилей"
иначе если n % 10 == 1 то
  "автомобиль"
иначе
  "автомобиля"
Похожие вопросы