所引用的表定义为:
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
);
此查询的预期结果集应该由行中的每个用户行组成,并为以下内容提供列:
user_id
:用户ID message_count
:每个用户在两个日期时间定义的间隔内发送的消息数(如果没有发送消息,则为0)voice_time
:在两个日期时间定义的时间间隔内,每个语音会话的最后一次持续时间之和(如果没有语音会话处于活动状态,则应为0)active_days
:用户发送消息或进行有效语音会话的天数(如果用户在提供的时间间隔内未处于活动状态,则应为0)这是我写的查询:
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
这就是结果集的样子:
|user_id |message_count |voice_time |active_days |
|--------------------|--------------------|--------------------|--------------------|
|1 |752 |694 |1 |
|2 |12 |543 |2 |
|3 |323 |7163 |4 |
|4 |56 |870 |3 |
答案 0 :(得分:2)
对我来说,它看起来可读性强。
也许您可以将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 ...