Postgres查询:在下一个

时间:2017-04-26 22:18:41

标签: postgresql recursion case lag coalesce

我尝试将我在代码中的内容实现为postgres查询。 以下示例并不完全是我们尝试做的事情,但我希望它能说明我是如何尝试使用之前计算出的行中的值的。

示例表,以帮助我演示我尝试做的事情:

test=# select * from test ;
 id | field1 | field2 | field3 | score
----+--------+--------+--------+-------
  1 |      1 |      3 |      2 |  1.25
  2 |      1 |     -1 |      1 |
  3 |      2 |      1 |      5 |
  4 |      3 |     -2 |      4 |

这是正在进行的查询:

select id,
    coalesce (
            score,
            case when lag_field3 = 2 then 0.25*(3*field1+field2) end
    ) as new_score
from (
    select id, field1, field2, field3, score,
    lag (field3)  over (order by id) as lag_field3
    from test
) inner1 ;

到目前为止返回我想要的内容......

 id | new_score
----+-----------
  1 |      1.25
  2 |       0.5
  3 |
  4 |

查询的下一次迭代:

select id,
    coalesce (
            score,
            case when lag_field3 = 2 then 0.25*(3*field1+field2) end,
            case when field1 = 2 then 0.75 * lag (new_score) end
    ) as new_score
from (
select id, field1, field2, field3, score,
    lag (field3)  over (order by id) as lag_field3
from test
) inner1 ;

区别在于:

case when field1 = 2 then 0.75 * lag (new_score) end

我知道并理解为什么这不起作用。

我将计算字段别名为new_score,而当field1 = 2时,我想要0.75 *之前的行new_score值。 我知道new_score是一个别名,无法使用。

我有什么方法可以做到这一点吗?我可以尝试复制该表达式,在其周围包含一个滞后,将其作为别的东西,并尝试使用它,但这会变得非常混乱。

有什么想法吗?

非常感谢。

1 个答案:

答案 0 :(得分:0)

Postgres允许您在CASE语句中使用窗口。可能你错过了OVER (ORDER BY id)部分。您还可以定义不同的窗口,但不能将窗口与GROUP BY结合使用。此外,它不会让你使用ann窗口,所以你必须写下一些子查询或CTE。

以下是查询:

SELECT id, COALESCE(tmp_score,
                    CASE 
                        WHEN field1 = 2 
                            THEN 0.75 * LAG(tmp_score) OVER (ORDER BY id) 
                            -- missing ELSE statement here
                    END
           ) AS new_score
FROM (
    SELECT id, field1,
        COALESCE (
                score,
                CASE 
                    WHEN LAG(field3) OVER (ORDER BY id) = 2 
                    THEN 0.25*(3*field1+field2) 
                END
        ) AS tmp_score
    FROM test
) inner1

创建和填充表格的代码:

CREATE TABLE test(
    id int,
    field1 int,
    field2 int,
    field3 int,
    score numeric
);

INSERT INTO test VALUES
(1, 1, 3, 2, 1.25),
(2, 1, -1, 1, NULL),
(3, 2, 1, 5, NULL),
(4, 3, -2, 4, NULL);

查询返回此输出:

 id | new_score 
----+-----------
  1 |      1.25
  2 |      0.50
  3 |    0.3750
  4 |