Postgresql 如何简化这个复杂的查询?
参考的表格定义如下:Postgresql 如何简化这个复杂的查询?,postgresql,Postgresql,参考的表格定义如下: CREATE TABLE message ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, guild_id BIGINT NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP NOT NULL, ); CREATE TABLE d_user ( id BIGINT PRIMARY KEY ); CREATE TAB
CREATE TABLE message
(
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
guild_id BIGINT NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP NOT NULL,
);
CREATE TABLE d_user
(
id BIGINT PRIMARY KEY
);
CREATE TABLE vcsession
(
id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
guild_id BIGINT NOT NULL,
duration INTEGER NOT NULL,
began_at TIMESTAMP NOT NULL,
last_active TIMESTAMP NOT NULL
);
此查询的预期结果集应包括公会中每个用户的一行,并提供以下列:
:用户id用户id
:每个用户在两个日期时间定义的间隔内发送的消息数(如果未发送任何消息,则应为0)message\u count
:在两个日期时间定义的间隔内,每个语音会话上次活动的持续时间之和(如果没有语音会话处于活动状态,则该值应为0)voice\u time
:用户发送消息或进行活动语音会话的天数(如果用户在提供的时间间隔内未处于活动状态,则该天数应为0)active_days
select
activity.user_id,
message_count,
voice_time,
coalesce(active_days, 0) as active_days
from (
select
d_user.id as user_id,
coalesce(messages.count, 0) as message_count,
coalesce(vcsessions.duration, 0) as voice_time
from d_user left join (
select
user_id,
count(*) as "count"
from message where (
(guild_id = $1) and
(created_at >= $2) and
(created_at < $3)
) group by user_id
) as messages on messages.user_id = d_user.id left join (
select
user_id,
sum(duration) as "duration"
from vcsession where (
(guild_id = $1) and
(last_active >= $2) and
(last_active < $3)
) group by user_id
) as vcsessions on vcsessions.user_id = d_user.id
) as activity left join (
select user_id, count(*) as active_days from (
select * from (
select
user_id,
(cast(extract(EPOCH from message.created_at) as int) - cast(extract(EPOCH from $2) as int)) / 86400 as day_offset
from message where (
(created_at >= $2) and
(created_at < $3)
) group by user_id, day_offset
) as message_days union (
select
user_id,
(cast(extract(EPOCH from vcsession.last_active) as int) - cast(extract(EPOCH from $2) as int)) / 86400 as day_offset
from vcsession where (
(last_active >= $2) and
(last_active < $3)
) group by user_id, day_offset
)
) as active_days group by user_id
) as active_days on active_days.user_id = activity.user_id
对我来说,它看起来相当可读 也许您可以将forst
FROM
子句中的两个子选择拉入主查询:
SELECT ...
FROM ((SELECT ...) AS messages
LEFT JOIN
(SELECT ...) AS vcsessions
) AS ...
LEFT JOIN ...
可能成为
SELECT ...
FROM (SELECT ...) AS messages
LEFT JOIN
(SELECT ...) AS vcsessions
LEFT JOIN ...
对我来说,它看起来相当可读 也许您可以将forst
FROM
子句中的两个子选择拉入主查询:
SELECT ...
FROM ((SELECT ...) AS messages
LEFT JOIN
(SELECT ...) AS vcsessions
) AS ...
LEFT JOIN ...
可能成为
SELECT ...
FROM (SELECT ...) AS messages
LEFT JOIN
(SELECT ...) AS vcsessions
LEFT JOIN ...