我需要你的帮助。我想规范化组内的数字。说我有这个数据集:
A B C
-------
0 1 3
1 1 0
1 1 2
1 1 4
1 2 1
1 2 1
我想用A和B对这些行进行分组,然后将其中C 的值标准化,即对该组的所有C进行求和,然后将每个C除以该值和。在上面的例子中,我期望这个结果:
A B C
---------
0 1 1 // sum of C's in group is 1, 1/1=1
1 1 0 // sum of C's in group is 6, 0/6=0
1 1 1/3 // ...
1 1 2/3 // ...
1 2 1/2 // sum of C's in group is 2, 1/2=1/2
1 2 1/2 // ...
除以零可以单独处理。如何使用SQL(或PSQL,如果有帮助)这样做?我原则上可以想办法做到这一点,但我总是最终使用深度嵌套的SELECT,我想避免这种做法。
提前致谢!
答案 0 :(得分:6)
您可以使用窗口函数:
SELECT a,b,
1.0 * c / CASE WHEN SUM(c) OVER(PARTITION BY a,b) = 0 THEN 1
ELSE SUM(c) OVER(PARTITION BY a,b) END AS c
FROM tab
的 SqlFiddleDemo
强>
输出:
╔════╦════╦════════════════════╗
║ a ║ b ║ c ║
╠════╬════╬════════════════════╣
║ 0 ║ 1 ║ 1 ║
║ 1 ║ 1 ║ 0 ║
║ 1 ║ 1 ║ 0.3333333333333333 ║
║ 1 ║ 1 ║ 0.6666666666666666 ║
║ 1 ║ 2 ║ 0.5 ║
║ 1 ║ 2 ║ 0.5 ║
║ 2 ║ 2 ║ 0 ║ -- added for check division by 0
╚════╩════╩════════════════════╝
答案 1 :(得分:1)
您可以使用派生表来聚合值,然后将join
结果返回到原始表。为避免除0
,已包含where
子句。对于这些0
和的情况,您可能必须包含一个特殊条件来选择它们。
select t.a, t.b, 1.0 * t.c/t1.total_c
from tablename t
join (select a, b, sum(c) as total_c
from tablename
group by a, b) t1
on t.a = t1.a and t.b = t1.b
where t1.total_c > 0
答案 2 :(得分:0)
with t (a,b,c) as (values
(0, 1, 3),
(1, 1, 0),
(1, 1, 2),
(1, 1, 4),
(1, 2, 1),
(1, 2, 1),
(2, 2, 0)
)
select
a, b,
c::float / coalesce(nullif(sum(c) over(partition by a, b), 0), 1) as normal
from t
;
a | b | normal
---+---+-------------------
0 | 1 | 1
1 | 1 | 0
1 | 1 | 0.333333333333333
1 | 1 | 0.666666666666667
1 | 2 | 0.5
1 | 2 | 0.5
2 | 2 | 0