# Как переписать 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)
```