如何根据共享键的其他行进行聚合?
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;
自联接将为多个符合条件的姊妹行生成多个结果行。
从本质上讲,这可以归结为 relational-division 问题。特别是,因为...
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
我有一个 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;
自联接将为多个符合条件的姊妹行生成多个结果行。
从本质上讲,这可以归结为 relational-division 问题。特别是,因为...
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