# Как переписать SQL запросы для использования в Tarantool Привет, меня зовут Игорь, я разработчик решений на Tarantool в Mail.ru Group. Я работаю над витринами маркетинга в реальном времени для Мегафона, а также мейнтейню [tarantool/metrics](https://github.com/tarantool/metrics). Наши заказчики работают с Oracle SQL и при постановке задач просят переписывать аналитические/агрегирующие запросы с SQL на Tarantool *как-то по-другому надо написать, чтобы всем было понятно и про Lua и про то, что это запрос в тарантуле*. Далее я расскажу, как я пишу сложные запросы к распределенным спейсам в Тарантуле. ## Аналоги основных конструкций SQL ```sql SELECT ``` Аналогом SELECT-запросов в Тарантуле является ```lua box.space.space_name:pairs() ``` Эта функция возвращает итератор по всем записям из спейса. В тарантуле также есть функция `box.space.space_name:select()`, но я настоятельно не советую использовать ее на проде. `:select()` без указания лимита или без ключа приводит к блокировке инстанса тарантула. Аналогичено, никогда не делайте `box.space.space_name:pairs():totable()`. ```sql SELECT A, B, C FROM SPACE_NAME ``` ```lua box.space.space_name:pairs():map(function(x) return { A = x.A, B = x.B, C = x.C, } end) ``` ```sql WHERE ``` `WHERE` - фильтрующий запрос, который в тарантуле может быть выполнен с помощью ```lua box.space.space_name:pairs():filter(function(x) return x == smth end) ``` Если поле есть в индексе, то его можно указать в `pairs()`: ```sql SELECT A, B FROM SPACE_NAME WHERE A == '1' AND B < 10 ``` ```lua box.space.space_name.index.index_name:pairs({'1', 10}, {iterator = 'REQ'}) ``` ```sql ORDER BY ``` ```lua table.sort(table_to_sort, function(a, b) if a.firstField == b.firstField then if a.secondField == b.secondField then return false else return a.secondField > b.secondField end else return a.firstField > b.firstField end end) ``` ```sql= GROUP BY A, B, C ``` ```lua box.space.space_name:pairs():reduce(function(acc, x) local key = x.A .. x.B .. x.C if acc[key] or acc[key] = table.insert(acc[key], x) else acc[key] = {x} end return acc end, {}) ``` Собираем все вместе: ```sql SELECT A, B, C FROM SPACE_NAME WHERE A == '1' OR (B >= 2 and C IS LIKE '3*') ORDER BY A, B GROUP BY B, C ``` ```lua local result = box.space.space_name.index.index_name:pairs({'1', 2}, {iterator = 'GEQ'}): filter(function(x) return (x.C or ''):find('3') ~= nil): map(function(x) return { A = x.A, B = x.B, C = x.C, } end): reduce(function(acc, x) local key = x.B .. x.C if acc[key] or acc[key] = table.insert(acc[key], x) else acc[key] = {x} end end, {}) result = fun.iter(result):map(function(_, v) return v end):totable() table.sort(result, function(a, b) if a.A == b.A then if a.B == b.B then return false else return a.B > b.B end else return a.A > b.A end end) ```