Как перевести числовой массив в последовательность чисел для IN

Добрый день. Имеется таблица с такой структурой
0aa46fb80a90620c5978f8804031a1b3bad47bf7
В полях services и brands стоит тип - числовой массив.
В другой таблице имеются соответствия этим ключам.

Как сделать запрос который бы заджоинил эту таблицу и преобразовал идентификаторы к текстовому представлению ?
Такой запрос
select *,
//Вложенный запрос который представляет select * from unnest(services) наш массив как последовательность строк, а далее мы в этой последовательности ищем в таблице соответствий текстовое представление и потом опять же агрегируем это все в 1 строку.
(select string_agg(service,',') from autorepair_service where id in(select * from unnest(services))) from autorepair


Запрос получается мягко говоря тяжелый с точки зрения понимания. Может быть есть способ полегче ? Не нашел ни одной функции которая бы массив представляла как последовательность чисел через запятую, есть array to string которая преобразует массив в строку, но тогда эту строку не получается подставить в предикат IN, выпадает ошибка
operator does not exist: integer = text

Интересует сам вопрос. Делать связи один ко многим нет желания в связи с производительностью запроса.

select *,(
    select string_agg(service,',') 
              from autorepair_service 
    where id=any(services)) 
from autorepair

"Seq Scan on autorepair  (cost=0.00..18772.45 rows=5889 width=693) (actual time=0.143..120.302 rows=5590 loops=1)"
"  SubPlan 1"
"    ->  Aggregate  (cost=3.07..3.08 rows=1 width=36) (actual time=0.021..0.021 rows=1 loops=5590)"
"          ->  Seq Scan on autorepair_service  (cost=0.00..3.05 rows=10 width=36) (actual time=0.003..0.018 rows=29 loops=5590)"
"                Filter: (id = ANY (autorepair.services))"
"                Rows Removed by Filter: 62"
"Total runtime: 120.585 ms"


select *,(select string_agg(service,',') from autorepair_service where id in(select * from unnest(services))) from autorepair

"Seq Scan on autorepair  (cost=0.00..33899.82 rows=5889 width=693) (actual time=0.142..139.699 rows=5590 loops=1)"
"  SubPlan 1"
"    ->  Aggregate  (cost=5.64..5.65 rows=1 width=36) (actual time=0.024..0.024 rows=1 loops=5590)"
"          ->  Hash Semi Join  (cost=2.25..5.41 rows=91 width=36) (actual time=0.009..0.021 rows=29 loops=5590)"
"                Hash Cond: (autorepair_service.id = unnest.unnest)"
"                ->  Seq Scan on autorepair_service  (cost=0.00..1.91 rows=91 width=40) (actual time=0.001..0.005 rows=91 loops=5558)"
"                ->  Hash  (cost=1.00..1.00 rows=100 width=4) (actual time=0.006..0.006 rows=29 loops=5590)"
"                      Buckets: 1024  Batches: 1  Memory Usage: 1kB"
"                      ->  Function Scan on unnest  (cost=0.00..1.00 rows=100 width=4) (actual time=0.002..0.003 rows=29 loops=5590)"
"Total runtime: 140.058 ms"
  • Вопрос задан
  • 3085 просмотров
Решения вопроса 1
@Timosha
я смутно понял в чём действительно состоит вопрос, но быть может это поможет
where id in(select * from unnest(services))
можно заменить на
where id = any (services)
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
alekciy
@alekciy
Вёбных дел мастер
Вообще-то функция array_to_string принимает вторым параметром разделитель. Пример прямо в документации: www.postgresql.org/docs/9.3/static/functions-array.html

Но в целом у вас проблема с архитектурой и неправильным использованием реляционной базы. Потому что если там id записей другой таблицы, то в случае связи "многие-ко-многим" нужно просто "линковочная", промежуточная таблица.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы