Оптимизация SQL-запроса 2.0

Есть примитивная база данных магазина.

ER-диаграмма: введите сюда описание изображения

Создание (диалект PostgreSQL):

create table customer(
    id serial primary key, 
    name varchar(255),
    phone varchar(30),
    email varchar(255)); 

create table product( 
    id serial primary key,
    name varchar(255),
    description text,
    price integer);

create table cart(
    customer_id integer references customer(id),
    id serial primary key);
    
create table cart_product(
    cart_id integer references cart(id),
    product_id text)

insert into customer(name, phone, email) values
('Василий', '02', '[email protected]'),
('Петр', '04', '[email protected]');

insert into product(name, description, price) values
('IPhone', 'Luxury phone', 100000),
('Apple Watch', 'Cool watches', 50000);

insert into cart(customer_id) values
(1);

insert into cart_product (cart_id, product_id) values
(1, '1, 2');

Таблица cart_product содержит текстовое поле product_id, которое через запятую хранит id таблицы product.

Задача заключается в том, чтобы, объединив таблицы, получить информацию о клиенте и товарах, которые есть в заказе у этого клиента, причем товары должны быть в одном поле, перечисленные через запятую. Вопрос решен (см. листинг ниже), однако совершенно неоптимизированным образом - создаются дублирующиеся строки, которые после добавления product.name схлопываются обратно. Очевидно, что эту задачу можно решить быстрее (с помощью функций и т.п.) - не понимаю, как.

Код (диалект PostgreSQL):

select STRING_AGG(p.name, ', ') as products, cq.cus_name, cq.cus_email, cq.cart_id from 
(select 
cs.name as cus_name,
cs.email as cus_email,
c.id as cart_id, 
unnest(string_to_array(cp.product_id, ', ')) as product_id
from cart_product cp, cart c, customer cs
where c.id = cp.cart_id and
cs.id = c.customer_id) as cq left join product p 
on p.id = cq.product_id::integer
group by cq.cus_name, cq.cus_email, cq.cart_id

Результат работы с данными из примера (совпадает с ожидаемым, однако на больших данных считается долго): введите сюда описание изображения


Ответы (0 шт):