@antonowano
Профессиональный самоучка

Как переписать длинный запрос MySQL на эффективный PostgreSQL?

Есть вот такой рабочий запрос (прикрепил ниже). Он делает вывод подразделов следующего уровня с количеством услуг располагающихся в них учитывая 4 уровня вложенности разделов.

categories - таблица разделов, category_id указывает родителя;
services - таблица услуг, category_id указывает принадлежность к категории;
service_status - таблица статусов услуг, service_id - принадлежность к услуге, expires_at - время действия, если NULL, то бессрочный, type - преимущества (в частности "posted" означает, что услуга размещена);

Возможно ли его переписать на PostgreSQL, так чтобы запрос стал эффективнее, понятнее и работал вне зависимости от вложенности категории?

SELECT lvl1.id, lvl1.name, lvl1.alias,
  COUNT(s5.id) + COUNT(s4.id) + COUNT(s3.id) + COUNT(s2.id) + COUNT(s1.id) AS count

FROM categories lvl1
LEFT JOIN services p1 ON p1.category_id = lvl1.id
LEFT JOIN service_status s1 ON s1.service_id = p1.id AND s1.type = "posted" AND (s1.expires_at IS NULL OR s1.expires_at > CURRENT_TIMESTAMP())

LEFT JOIN categories lvl2 ON lvl2.category_id = lvl1.id
LEFT JOIN services p2 ON p2.category_id = lvl2.id
LEFT JOIN service_status s2 ON s2.service_id = p2.id AND s2.type = "posted" AND (s2.expires_at IS NULL OR s2.expires_at > CURRENT_TIMESTAMP())

LEFT JOIN categories lvl3 ON lvl3.category_id = lvl2.id
LEFT JOIN services p3 ON p3.category_id = lvl3.id
LEFT JOIN service_status s3 ON s3.service_id = p3.id AND s3.type = "posted" AND (s3.expires_at IS NULL OR s3.expires_at > CURRENT_TIMESTAMP())

LEFT JOIN categories lvl4 ON lvl4.category_id = lvl3.id
LEFT JOIN services p4 ON p4.category_id = lvl4.id
LEFT JOIN service_status s4 ON s4.service_id = p4.id AND s4.type = "posted" AND (s4.expires_at IS NULL OR s4.expires_at > CURRENT_TIMESTAMP())

LEFT JOIN categories lvl5 ON lvl5.category_id = lvl4.id
LEFT JOIN services p5 ON p5.category_id = lvl5.id
LEFT JOIN service_status s5 ON s5.service_id = p5.id AND s5.type = "posted" AND (s5.expires_at IS NULL OR s5.expires_at > CURRENT_TIMESTAMP())

WHERE lvl1.category_id = 5
GROUP BY lvl1.id
ORDER BY count DESC
  • Вопрос задан
  • 253 просмотра
Решения вопроса 1
longclaps
@longclaps
В стандартной поставке postgre есть расширение ltree (на момент написания хорошей, годной статьи его не существовало).
Update by Melkij: существовало аж с 2002 года.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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