1

我想在计算两列之间差异的地方进行查询。就像是:

 SELECT a,
        b,
        a - b as "diff"
  FROM ...

现在我想使用postgresql内置的stddev聚合函数计算“diff”列的stddev。我怎样才能做到这一点?

谢谢。

编辑:

实际查询是这样的:

SELECT tr.date_start,
       tr.date_end,       
       (((CASE when(tourney_summary.val_curr_conv != 0) THEN tourney_summary.val_curr_conv * (tr.amt_won + tr.cnt_bounty * tourney_summary.amt_bounty) ELSE 0.0 END))) AS "amt_won_curr_conv",
          (((CASE when(tourney_summary.val_curr_conv != 0) THEN tourney_summary.val_curr_conv * (tourney_summary.amt_buyin + tourney_summary.amt_fee + tourney_summary.amt_rebuy * tr.cnt_rebuy + tourney_summary.amt_addon * tr.cnt_addon + tourney_summary.amt_bounty) ELSE 0.0 END))) AS "amt_buyin_ttl_curr_conv",
       ((((CASE when(tourney_summary.val_curr_conv != 0) THEN tourney_summary.val_curr_conv * (tr.amt_won + tr.cnt_bounty * tourney_summary.amt_bounty) ELSE 0.0 END))) - (((CASE when(tourney_summary.val_curr_conv != 0) THEN tourney_summary.val_curr_conv * (tourney_summary.amt_buyin + tourney_summary.amt_fee + tourney_summary.amt_rebuy * tr.cnt_rebuy + tourney_summary.amt_addon * tr.cnt_addon + tourney_summary.amt_bounty) ELSE 0.0 END)))) as net_amt_won,
       stddev((((CASE when(tourney_summary.val_curr_conv != 0) THEN tourney_summary.val_curr_conv * (tr.amt_won + tr.cnt_bounty * tourney_summary.amt_bounty) ELSE 0.0 END))) - (((CASE when(tourney_summary.val_curr_conv != 0) THEN tourney_summary.val_curr_conv * (tourney_summary.amt_buyin + tourney_summary.amt_fee + tourney_summary.amt_rebuy * tr.cnt_rebuy + tourney_summary.amt_addon * tr.cnt_addon + tourney_summary.amt_bounty) ELSE 0.0 END)))) as diff_std_dev

FROM tourney_summary,
     tourney_results tr
WHERE 
  tr.id_player=1
  AND tourney_summary.id_tourney = tr.id_tourney
  AND ((tourney_summary.id_gametype = 1)
       AND (((((((tourney_summary.id_table_type IN
                    (SELECT lttt.id_table_type
                     FROM tourney_table_type lttt
                     WHERE lttt.val_seats = 2))))))
             AND (((((tourney_summary.id_table_type IN
                        (SELECT lttt.id_table_type
                         FROM tourney_table_type lttt
                         WHERE position('S' IN lttt.val_speed) > 0))
                     OR (tourney_summary.id_table_type IN
                           (SELECT lttt.id_table_type
                            FROM tourney_table_type lttt
                            WHERE position('H' IN lttt.val_speed) > 0))))))))
       AND ((tourney_summary.date_start >= '2013/08/15 23:00:00')))
GROUP BY tr.date_start,
         tr.date_end,
         tourney_summary.val_curr_conv,
         tr.amt_won,
         tr.cnt_bounty,
         tourney_summary.amt_bounty,
         tourney_summary.amt_buyin,
         tourney_summary.amt_fee,
         tourney_summary.amt_rebuy,
         tr.cnt_rebuy,
         tourney_summary.amt_addon,
         tr.cnt_addon
ORDER BY tr.date_end DESC;

“a”和“b”表达式(带有 CASE 的表达式)很大。而且我不知道如何避免复制/粘贴。在任何情况下,在 ab 表达式上使用 stddev 都会返回一个空白列。我究竟做错了什么?

谢谢。

4

2 回答 2

3

你几乎自己回答。计算差值的标准差:

 SELECT a,
        b,
        a - b as "diff",
        stddev(a - b) AS "diff_stddev"
  FROM ...

如果a - b是一个计算量大的操作,或者实际上是一个更复杂的表达式,您可以将它包装在一个子查询中:

 SELECT a, b, "diff", stddev("diff") AS diff_stddev
 FROM (
   SELECT a, b, a - b
   FROM ...
 ) x (a, b, "diff")

x只是子查询表的一次性别名。

于 2013-08-17T16:25:32.393 回答
2

也可以用 cte 做到这一点

with cte1 as (
   select a, b, a - b as diff
   from ...
)
select
    a, b, diff, stddev(diff) as diff_stddev
from cte1
于 2013-08-17T16:30:58.913 回答