为什么我的窗口函数似乎使用了整个数据集?

问题描述 投票:0回答:1

我有这个查询,但最大值和平均值似乎没有按预期工作:

SELECT 
    UPPER(SUBSTR(first_query.periodname, 1,3)) AS month,
    ROUND(first_query.amount) AS amount,
    ROUND(MAX(first_query.amount) OVER (ORDER BY first_query.postingPeriod ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)) AS maxamount,
    ROUND(AVG(first_query.amount) OVER (ORDER BY first_query.postingPeriod ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)) AS avgamount,
    ROUND(LAG(first_query.amount) OVER (ORDER BY first_query.postingPeriod)) AS lagamount,
    ROUND(LEAD(first_query.amount) OVER (ORDER BY first_query.postingPeriod)) AS leadamount
FROM (
    SELECT
        SUM(tl.foreignamount * t.ExchangeRate * -1) AS amount,
        BUILTIN.DF(t.postingPeriod) AS periodname,
        t.postingPeriod
    FROM
        Transaction t
    JOIN transactionline tl ON t.id = tl.transaction
    JOIN account a ON a.id = tl.expenseaccount
    WHERE
        EXTRACT(YEAR FROM t.trandate) = 2023  
    GROUP BY
        BUILTIN.DF(t.postingPeriod),
        t.postingPeriod
    ORDER BY
        t.postingPeriod
) AS first_query
ORDER BY
    first_query.postingPeriod;

其结果是:

金额 最大金额 平均金额 拉加蒙 铅量
一月 1833916 1833916 1833916 1857884
二月 1857884 1857884 1845900 1833916 2048416
三月 2048416 2048416 1913405 1857884 1731385
四月 1731385 2048416 1867900 2048416 1543348
五月 1543348 2048416 1802990 1731385 1642432
六月 1642432 2048416 1776230 1543348 1541351
七月 1541351 2048416 1742676 1642432 1862392
八月 1862392 2048416 1757640 1541351 1377795
九月 1377795 2048416 1715435 1862392 1324765
十月 1324765 2048416 1676368 1377795 1042649
十一月 1042649 2048416 1618758 1324765 1365764
十二月 1365764 2048416 1597675 1042649

因此您可以看到滞后和超前效果很好,但是很容易看到最大值不起作用。据我所知,它只是不断地将新行添加到窗口中。

对我缺少的东西有什么想法吗?谢谢!

sql
1个回答
0
投票

不太确定窗口函数出了什么问题,但找到了使用 rownum 和 WITH 子查询的解决方法。相当混乱,但至少它可以工作。

WITH first_query AS (
    SELECT
        t.postingPeriod AS postingperiod,
        BUILTIN.DF(t.postingPeriod) AS periodname,
        SUM(tl.foreignamount * t.ExchangeRate * -1) AS amount
    FROM
        Transaction t
    JOIN
        TransactionLine tl ON t.id = tl.transaction
    WHERE
        EXTRACT(YEAR FROM t.trandate) = 2023
    GROUP BY
        t.postingPeriod,
        BUILTIN.DF(t.postingPeriod)
),
second_query AS (
    SELECT
        rownum,
        postingperiod,
        periodname,
        ROUND(amount) AS amount
    FROM
        first_query
),
final_query AS (
    SELECT 
        rownum,
        postingperiod,
        periodname,
        amount,
        (SELECT MAX(sq.amount) 
         FROM second_query sq
         WHERE sq.rownum BETWEEN second_query.rownum - 1 AND second_query.rownum + 1) AS max_amount,
        (SELECT AVG(sq.amount) 
         FROM second_query sq
         WHERE sq.rownum BETWEEN second_query.rownum - 1 AND second_query.rownum + 1) AS avg_amount
    FROM 
        second_query
)
SELECT 
    UPPER(SUBSTR(periodname, 1, 3)) AS month,
    ROUND(amount) AS amount,
    ROUND(max_amount) AS maxamount,
    ROUND(avg_amount) AS avgamount
FROM 
    final_query
ORDER BY 
    postingperiod;
© www.soinside.com 2019 - 2024. All rights reserved.