2014-11-14 75 views
1

我在SQL表中有几列,我想计算表中每一行的结果。我的数据看起来是这样的:SQL查询:获取每行的调整值

data 
name  value adjustor1 adjustor2 
Comp1 20  0.05  0.08 
Comp2 80  -0.07  0.065 

的每一行的调整值的计算公式为:

adjusted_value = value*(1 + adjustor1)*(1 + adjustor2)*(100/sum(value)) 

所以调整后的输出应该是:

data 
name  adjusted_value 
Comp1 22.25 
Comp2 77.75 

原始值总和到100,调整后的值也应该总和为100.我试过的东西如:

SELECT adjusted*(100/sum(adjusted)) 
FROM (
     SELECT value*(1+adjustor1)*(1+adjustor2) as adjusted 
     FROM data 
) as result 

它给我的错误:ERROR: column "result.adjusted" must appear in the GROUP BY clause or be used in an aggregate function

但如果我只是做:

SELECT sum(adjusted) 
FROM (
     SELECT value*(1+adjustor1)*(1+adjustor2) as adjusted 
     FROM data 
) as result 

OR

SELECT adjusted 
FROM (
     SELECT value*(1+adjustor1)*(1+adjustor2) as adjusted 
     FROM data 
) as result 

我能得到任何总和或调整值,但不能同时。

回答

1

列名value是不是一个好的选择,这是一个保留字。我将其改为val

这是你需要查询:

WITH data(name,val,adjustor1,adjustor2) AS (
    VALUES 
    ('Comp1'::text,20,0.05,0.08), 
    ('Comp2',80,-0.07,0.065) 
) 
SELECT name,val,adjustor1,adjustor2, 
     CAST(val*(1+adjustor1)*(1+adjustor2)*(100/sum(
     val*(1+adjustor1)*(1+adjustor2) 
     ) OVER()) AS numeric(10,3)) adjusted_value 
    FROM data; 

我必须承认,这是一个有点笨拙,子查询可以更容易地理解(SQL Fiddle):

WITH data(name,val,adjustor1,adjustor2) AS (
    VALUES 
    ('Comp1'::text,20,0.05,0.08), 
    ('Comp2',80,-0.07,0.065) 
) 
SELECT name, CAST(adj*(100/sum(adj) OVER()) AS numeric(8,3)) adjusted_value 
    FROM (
    SELECT name,val,adjustor1,adjustor2, 
      val*(1+adjustor1)*(1+adjustor2) adj 
     FROM data) s; 

一些注意事项:

  • 原始sum(adj)被替换为sum(adj) OVER(),这是0123的语法。
  • 我也加了[CAST()][3]为了收集数值。
+0

我一直在玩OVER(?)语法一段时间,但我无法弄清楚把它放在哪里。这看起来很完美,消除了重复子查询或交叉连接的需要。 – 2014-11-14 19:44:04

0

你可以得到一个子查询的SUM,然后你可以做CROSS JOIN达到你想要什么

SELECT name, 
     value*(1+adjustor1)*(1+adjustor2)*(100/T.adjSum) as adjusted_value 
FROM data 
CROSS JOIN 
(SELECT SUM(value*(1+adjustor1)*(1+adjustor2)) as adjSum 
FROM data) T