postgresql: упростить код получения строки с уникальными словами, избавиться от лишних функций
есть такой sql запрос
SELECT
t1.id AS id,
array_to_string(
array(
SELECT DISTINCT unnest(
string_to_array(
STRING_AGG(t2.words, '|')
, '|')
)
)
, '|') AS words
FROM libraries t1
JOIN library_file_relationships r ON t1.id = r.library_id
JOIN files t2 ON r.file_id = t2.id
GROUP BY t1.id
- из таблицы
filesизвлекаются поляwords, которые содержат слова, разделённые разделителем '|' - затем поля разбиваются на отдельные слова по разделителю '|' и преобразуются в массив
- из массива оставляются только уникальные значения
- которые затем опять складываются в строку через разделитель '|'
Я сделал в лоб, что данный алгоритм гарантированно работает, но как по мне происходит очень много лишних функций работы со строками и массивами, как мне кажетяся
можно ли его упростить (а значит и ускорить)?
Нужно: в каждой группе из полученных строк, содержащих слова через разделитель '|', создать одну строку, содержащие только уникальные слова (без повторов) через разделитель '|'
Ответы (1 шт):
Можно упростить разборку-сборку так
select id,string_agg(w1,'|') as words
from (
select distinct id,string_to_table(fl.words,'|') w1
from files fl
)x
group by id;
Должно получиться примерно так:
SELECT t1.id AS id,t2.words
FROM libraries t1
JOIN library_file_relationships r ON t1.id = r.library_id
JOIN (select id,string_agg(w1,'|') as words
from (
select distinct id,string_to_table(fl.words,'|') w1
from files fl
)x
group by id
)t2 ON r.file_id = t2.id
GROUP BY t1.id -- нужно ли это, вопрос
По комментарию, больше вариант
SELECT t1.id AS id,t2.words
FROM libraries t1
JOIN library_file_relationships r ON t1.id = r.library_id
JOIN (select library_id,string_agg(w1,'|') as words
from (
select distinct library_id,string_to_table(fl.words,'|') w1
from files fl
JOIN library_file_relationships r ON fl.id = r.library_id
)x
group by library_id
)t2 ON r.library_id = t2.library_id
Ваш вариант:Собрать 1-10000 строк в одну и потом разобрать на слова, выбрать уникальные и собрать в строку. И повторить это 10000 раз.
Предлагаемый: Разобрать 1000 000 строк на слова и собрать в готовую строку для каждого library_id (libraries.id) уникальные в пределах library_id.
Представляется, string_agg внутренний - можно пропустить и собирать DISTINCT по library_id. Умозрительно, это позволит не создавать 1 временную таблицу размером с files.
В любом случае, придется создавать временную таблицу на несколько миллионов строк(слов) и сортировать его по library_id и words.
Если запрос слишком тяжелый, делать поэтапно, по, например, 1000 library_id.