如何根据共享键的其他行进行聚合?

How to aggregate based on other rows that share a key?

我有一个 table 格式如下:

我觉得这应该很简单,但我正在努力想出一个高性能查询,该查询可以使用共享键基于其他行执行聚合。例如,我想对具有键 MediaLength 的用户的行求和,但前提是具有键 Score 且共享 event_id 的行大于或等于 3。

简单求和的结果:

SELECT SUM(value::float) FROM data WHERE key = 'MediaLength' AND user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'

Result: 40

我在这里试图达到的结果是 15。在上面的 table 中,您可以看到行是事件的子项。我只想对 value 列求和,其中 key = 'MediaLength' 及其姊妹行 key = 'Score' 具有 value >= 3.

这是我迄今为止尝试过的查询,但它看起来有点乱,而且由于 more than one row returned by subquery 错误而无法正常工作:

select
    sum(value::float)
        filter (where (
            select d.value::float
            from data d
            where d.event_id = event_id
            and d.key = 'Score'
        ) >= 3)
from data
where user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'

这是一个简单的示例,但将来我可能还需要过滤其他多个键,因此我们也非常感谢任何关于如何扩展它的建议。

I only want to sum the value column where key = 'MediaLength' and its sister row with key = 'Score' has value >= 3.

SELECT sum(value::float)  -- why the cast?
FROM   data d
WHERE  user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'
AND    key = 'MediaLength'
AND    EXISTS (
   SELECT FROM data ds
   WHERE  ds.event_id = d.event_id
   AND    ds.user_id = d.user_id    -- !
   AND    ds.key = 'Score'
   AND    ds.value >= 3
   );

此处,如果 任何 姐妹通过过滤器,则具有 key = 'MediaLength' 的行符合条件。 (可能还有更多的姐妹考不上。)

如果永远只能有一个单个符合条件的姊妹行(由唯一约束/索引强制执行?),自连接会更简单一些:

SELECT sum(value::float)
FROM   data d
JOIN   data ds USING (event_id, user_id)
WHERE  d.user_id = '9765f312-0d0b-4db0-b4c5-217eec81d7c3'
AND    d.key = 'MediaLength'
AND    ds.key = 'Score'
AND    ds.value >= 3;

自联接将为多个符合条件的姊妹行生成多个结果行。

从本质上讲,这可以归结为 问题。特别是,因为...

in the future I would need to filter on potentially multiple other keys as well

参见:

  • How to filter SQL results in a has-many-through relation