我正在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
=>所有关联活动的最小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;
答案 0 :(得分:1)
我认为您想要汇总。您的逻辑和结果表明:
select eventid, min(startDate), max(endDate),
(case when min(status) = max(status) and min(status) = 'Approved'
then 'Approved'
else 'Pending'
end) as status
from activities a
group by eventid;