Я работаю в PostgreSQL 9.6.6 над запросом, который предполагает использование второй таблицы для возврата дополнительных точек данных. Таблица - «события» - связана со многими записями из второго - «действия» - через внешний ключ.
События
| id | name |
|----|--------|
| 1 | event1 |
| 2 | event2 |
| 3 | event3 |
Мероприятия
| id | name | startDate | endDate | status | eventId |
|----|-----------|------------------------|------------------------|-----------|---------|
| 1 | activity1 | 2018-08-27 05:00:00+00 | 2018-08-28 05:00:00+00 | Draft | 1 |
| 2 | activity2 | 2018-09-27 05:00:00+00 | 2018-09-27 10:00:00+00 | Submitted | 1 |
| 3 | activity3 | 2018-08-25 05:00:00+00 | 2018-08-27 10:00:00+00 | Draft | 1 |
| 4 | activity4 | 2018-08-21 05:00:00+00 | 2018-08-24 05:00:00+00 | Approved | 2 |
| 5 | activity5 | 2018-09-27 05:00:00+00 | 2018-09-29 05:00:00+00 | Draft | 2 |
| 6 | activity6 | 2018-10-27 05:00:00+00 | 2018-10-28 05:00:00+00 | Approved | 3 |
| 7 | activity7 | 2018-08-27 05:00:00+00 | 2018-08-27 10:00:00+00 | Approved | 3 |
Точками данных, собираемыми с помощью события, являются startDate
, endDate
& status
на основе связанных действий.
startDate
=> Наименьшая начальная дата всех связанных действий.
endDate
=> Величайшая конечная дата всех связанных действий.
status
=> Статус равен «Ожидание», если не все связанные действия
имеют статус «Одобрено» (тогда статус равен «Завершено»).
Пример возвращаемого запроса будет выглядеть так:
| id | name | startDate | endDate | status |
|----|--------|------------------------|------------------------|-----------|
| 1 | event1 | 2018-08-25 05:00:00+00 | 2018-09-27 10:00:00+00 | Pending |
| 2 | event2 | 2018-08-21 05:00:00+00 | 2018-09-29 05:00:00+00 | Pending |
| 3 | event3 | 2018-08-27 05:00:00+00 | 2018-10-28 05:00:00+00 | Completed |
Я сформулировал следующее с несколькими подзапросами, но производительность ужасна.
Как я могу улучшить это, чтобы ограничить (или даже удалить) использование подзапросов?
SELECT DISTINCT ON("startDate", "event"."name") 1, "event"."id", "event"."name", (
SELECT "activities"."startDate"
FROM "events"
INNER JOIN "activities" AS "activities" ON "event"."id" = "activities"."eventId"
WHERE "event"."id" = "activities"."eventId"
ORDER BY "event"."id" ASC, "activities"."startDate" ASC
LIMIT 1
) AS "startDate", (
SELECT "activities"."endDate"
FROM "events"
INNER JOIN "activities" AS "activities" ON "event"."id" = "activities"."eventId"
WHERE "event"."id" = "activities"."eventId"
ORDER BY "event"."id" ASC, "activities"."endDate" DESC
LIMIT 1
) AS "endDate", (
SELECT DISTINCT ON("event"."id")
CASE "activities"."status"
WHEN 'Draft' THEN 'Pending'
WHEN 'Submitted' THEN 'Pending'
ELSE 'Complete'
END
FROM "events"
INNER JOIN "activities" AS "activities" ON "event"."id" = "activities"."eventId"
WHERE "event"."id" = "activities"."eventId"
ORDER BY "event"."id" ASC, "activities"."status" DESC
) AS "status"
FROM "events" AS "event"
ORDER BY "startDate" DESC, "event"."name" ASC
LIMIT 20
OFFSET 0;