使用SQL规范化组内的值

时间:2015-12-29 14:52:56

标签: sql postgresql

我需要你的帮助。我想规范化组内的数字。说我有这个数据集:

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,我想避免这种做法。

提前致谢!

3 个答案:

答案 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