Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Postgresql 如何简化这个复杂的查询?_Postgresql - Fatal编程技术网

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
  • message\u count
    :每个用户在两个日期时间定义的间隔内发送的消息数(如果未发送任何消息,则应为0)
  • voice\u 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

对我来说,它看起来相当可读

也许您可以将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 ...