【问题标题】:Exclude nulls from postgres window function从 postgres 窗口函数中排除空值
【发布时间】:2021-07-16 19:26:18
【问题描述】:

对于每一行,我想取最后 20 个非空值的平均值。

窗口函数取下面的 20 行,包括空行并计算平均值,而我想要最后 20 个非空行的平均值。

我尝试了什么?

WITH adv_calculated AS (
    SELECT security_id                                                                               AS sec_id,
           date                                                                                      AS pd,
           AVG(volume)
           OVER (PARTITION BY (security_id) ORDER BY date ROWS BETWEEN 20 PRECEDING AND CURRENT ROW) AS adv
    FROM tbl_financial_index_data
    WHERE volume IS NOT NULL
    GROUP BY security_id, date
)
UPDATE tbl_financial_index_data
SET adv                  = amc.adv
FROM adv_calculated amc
WHERE amc.sec_id = security_id
  AND amc.pd = date

此解决方案适用于 volume 不为 null 的所有行,但它不会计算 volume 为 NULL 的行的 adv/average。 然后对于 null adv 和 volume 行,我必须运行这个非常慢的查询

UPDATE tbl_financial_index_data
SET average_daily_volume =
        (SELECT avg(t.volume)
         FROM (
                  SELECT a.volume
                  FROM tbl_financial_index_data a
                  WHERE a.security_id = tbl_financial_index_data.security_id
                    AND a.date::date <= tbl_financial_index_data.date::date
                    AND a.volume IS NOT NULL
                  ORDER BY a.date DESC
                  LIMIT 21
              ) t)
WHERE volume IS NULL;

我想避免使用第二个查询并使用第一个查询计算所有行的 ADV(因为它要快得多)。

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    只需省略WHERE 条件WHERE volume IS NOT NULL,那么你应该得到你想要的。

    您可以将查询嵌套在外部查询中,以便稍后删除不需要的值:

    WITH adv_calculated AS (
       SELECT ...
       FROM (SELECT AVG(volume) OVER (... ROWS BETWEEN ... AND ...),
                    ...
             FROM tbl_financial_index_data
             GROUP BY security_id, date
            ) AS subq
       WHERE volume IS NOT NULL
    )
    SELECT ...
    

    【讨论】:

    • 我不明白,如果我省略 where 条件,那么我 21 天的平均值将包括我不想要的空量值。
    • 那我一个不懂的问题。如果您不想要 NULL,那么您的问题中的查询有什么问题?
    • 问题中的查询不会更新/计算volume为null的行的adv,因为我排除了它。它工作正常,并且只为那些体积不为 nulll 的行计算 adv。我希望计算 adv(平均值),但我也希望从该平均值中排除空量。
    • 也许您可以告诉我 NULL 列将如何影响平均值。
    • 请以文本形式提供示例数据 - 无图片,(或fiddle)。还包括该数据的预期结果以及您当前得到的结果 - 也没有图像。
    【解决方案2】:

    这只是一个变通方法

    好的,所以我找到了解决方案。 如果某行的卷为空,则该行的广告将等于前一个非空卷行的广告,因此我必须找到某种方法来为它为空的行结转先前的非空广告.

    我能够从 answer 找到一种方法。

    下面是继承非空值的代码:

    WITH temp_adv_filled_values AS (
        SELECT security_id,
               date,
               FIRST_VALUE(adv) OVER W                  AS adv
        FROM (
                 SELECT security_id,
                        date,
                        adv,
                        SUM(CASE WHEN volume IS NULL THEN 0 ELSE 1 END)
                        OVER (PARTITION BY security_id ORDER BY date ) AS value_partition
                 FROM tbl_financial_index_data
             ) AS q
            WINDOW W AS (PARTITION BY security_id, value_partition ORDER BY date)
    )
    UPDATE tbl_financial_index_data tfid
    SET adv                  = tmcfv.adv
    FROM temp_adv_filled_values tmcfv
    WHERE tmcfv.security_id = tfid.security_id
      AND tmcfv.date = tfid.date;
    

    【讨论】:

    • 。 .我看不出它如何处理“最后 20 个非空值”。
    • 你说得对,这更像是一种解决方法来实现同样的目标。
    • 。 .你有一个非常明确的问题。如果这是答案,那么问题就不清楚了。我不会投反对票或投票结束,但这并不能回答您提出的问题。
    • @GordonLinoff 我已经更新了答案,说这只是解决问题的方法,问题仍然存在。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-27
    • 1970-01-01
    • 2018-12-13
    相关资源
    最近更新 更多