gpt4 book ai didi

sql - Postgres : Simplify SQL query to get rid of subselects

转载 作者:行者123 更新时间:2023-11-29 14:13:29 27 4
gpt4 key购买 nike

我有一个 events 表,其中包含各种创建、完成和失败事件。每个事件都有一个 ID(表中的主键),还有一个“entity_id”,它将多个事件链接在一起。

例如,当一个请求被创建然后完成时,我们会有两个事件:

  • 请求 #42 已创建
  • 请求 #42 已完成

在上面的例子中,42是请求的entity_id。

CREATE TABLE IF NOT EXISTS events (
id SERIAL PRIMARY KEY,
entity_id INTEGER NOT NULL,
type VARCHAR(255) NOT NULL,
occurred_at TIMESTAMP NOT NULL
);

INSERT INTO events (entity_id, type, occurred_at) VALUES
(1, 'created', '2019-08-08 11:20:04.791592+00'),
(1, 'completed', '2019-08-08 11:20:05.791592+00'),
(2, 'created', '2019-08-08 11:20:06.791592+00'),
(2, 'failed', '2019-08-08 11:20:07.791592+00'),
(3, 'created', '2019-08-08 11:20:08.791592+00'),
(3, 'completed', '2019-08-08 11:20:09.791592+00');

我想创建该表的 View ,以便每个 entity_id 都与创建和完成/失败时间相关联。

对该 View 的查询应返回以下结果:

 entity_id |         created_at         |        completed_at        |         failed_at          
-----------+----------------------------+----------------------------+----------------------------
1 | 2019-08-08 11:20:04.791592 | 2019-08-08 11:20:05.791592 |
2 | 2019-08-08 11:20:06.791592 | | 2019-08-08 11:20:07.791592
3 | 2019-08-08 11:20:08.791592 | 2019-08-08 11:20:09.791592 |

我尝试使用 left join,但没有得到任何好的结果。到目前为止,我最好的尝试是:

SELECT
e.entity_id,
e.occurred_at as created_at,
(SELECT occurred_at FROM events WHERE type = 'completed' AND entity_id = e.entity_id) AS completed_at,
(SELECT occurred_at FROM events WHERE type = 'failed' AND entity_id = e.entity_id) AS failed_at
FROM events e
WHERE e.type = 'created';

这对我来说似乎很不优雅,而且可能也很低效。

你能推荐一个更好的选择吗?我正在使用 postgres,并且很高兴使用 postgres 特定的功能。

最佳答案

您可以使用窗口函数:

SELECT e.*
FROM (SELECT e.entity_id,
e.occurred_at as created_at,
MAX(e.occurred_at) FILTER (WHERE type = 'completed') OVER (PARTITION BY e.entity_id) AS completed_at,
MAX(e.occurred_at) FILTER (WHERE type = 'failed') OVER (PARTITION BY e.entity_id) AS failed_at
FROM events e
) e
WHERE e.type = 'created';

但是,聚合可能更合适:

SELECT e.entity_id,
MAX(e.occurred_at) FILTER (WHERE type = 'created') as created_at,
MAX(e.occurred_at) FILTER (WHERE type = 'completed') AS completed_at,
MAX(e.occurred_at) FILTER (WHERE type = 'failed') AS failed_at
FROM events e
GROUP BY e.entity_id;

关于sql - Postgres : Simplify SQL query to get rid of subselects,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57411923/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com