在PostgreSQL中加入时重复计数

时间:2019-01-10 12:58:23

标签: sql postgresql count left-join

我有下表:

用户,其中包含以下列:

id: INT
name: VARCHAR
boss_id: INT

首领,其中包含以下列:

id: INT
name: VARCHAR

消息,其中包含以下列:

author_id: INT (reference to users)
body: VARCHAR
type: VARCHAR

messages_targets 包含以下列:

user_id: INT (reference to users)
message_id: INT (reference to messages)

现在,我有以下查询可以正确地向我返回每个老板的用户比例,即收到至少一条“紧急”类型消息的用户所占的百分比查询:

SELECT (COUNT(DISTINCT CASE WHEN messages.type = 'urgent' THEN users.id END)::float / NULLIF(COUNT(DISTINCT users.id)::float, 0)) * 100,
bosses.id
FROM bosses
LEFT JOIN users ON users.boss_id = bosses.id
LEFT JOIN messages_targets ON messages_targets.user_id = users.id
LEFT JOIN messages ON messages.id = messages_targets.message_id
GROUP BY bosses.id

现在,我想修改该查询,以便它也返回我,用户已按老板分组编写的紧急消息数。因此,我已经尝试过:

SELECT (COUNT(DISTINCT CASE WHEN messages.type = 'urgent' THEN users.id END)::float / NULLIF(COUNT(DISTINCT users.id)::float, 0)) * 100 as percentage_received,
COUNT(CASE WHEN authored_messages.type = 'urgent' THEN 1 END) authored_messages_count
bosses.id
FROM bosses
LEFT JOIN users ON users.boss_id = bosses.id
LEFT JOIN messages_targets ON messages_targets.user_id = users.id
LEFT JOIN messages ON messages.id = messages_targets.message_id
LEFT JOIN messages authored_messages ON messages.author_id = users.id
GROUP BY bosses.id

但这不起作用。似乎是重复计算了一些数据。

以下是一些示例数据,并遵循我的预期:

bosses (id, name)
1, John
2, Charles

users (id, name, boss_id)
1, Mai, 1
2, Donald, 1
3, Denver, 2

messages (author_id, body, type)
1, 'message from Mai to Donald', 'urgent'
2, 'message from Donald to Denver', 'normal'
3, 'message from Denver to Mai', 'urgent'
4, 'message from Mai to Donald', 'urgent'

messages_targets (user_id, message_id)
2, 1
3, 2
1, 3 
2, 4

我希望得到以下信息:

boss_id, percentage_received, authored_messages

1, 100, 2 # (Both Mai and Donald received urgent messages, and in total there were 2 urgent messages sent)
2, 0, 1 # (Denver did not receive any urgent messages, but he sent one message)

1 个答案:

答案 0 :(得分:0)

尝试以下查询。它将两个聚合保持分开,因此它们的连接不会互相影响

SELECT 
    (
        SELECT 
           COUNT(DISTINCT CASE WHEN messages.type = 'urgent' THEN users.id END)::float / 
           NULLIF(COUNT(DISTINCT users.id)::float, 0)) * 100 
        FROM users
        JOIN messages_targets ON messages_targets.user_id = users.id
        JOIN messages ON messages.id = messages_targets.message_id
        WHERE users.boss_id = bosses.id
    ) percentage_received,
    (
        SELECT 
            COUNT(CASE WHEN messages.type = 'urgent' THEN 1 END) authored_messages_count
        FROM users
        JOIN messages_targets ON messages_targets.user_id = users.id
        JOIN messages ON messages.author_id = users.id
        WHERE users.boss_id = bosses.id
    ) authored_messages_count
    bosses.id
FROM bosses