窗口函数过滤当前行

2024-02-23

这是后续this https://stackoverflow.com/questions/48000013/optimize-slow-aggregates-in-lateral-join问题,我的查询被改进为使用窗口函数而不是内部的聚合LATERAL加入。虽然现在查询速度快得多,但我发现结果不正确。

我需要对 x 年跟踪时间范围执行计算。例如,price_to_maximum_earnings通过获取每行计算max(earnings)十多年前到当前行,并除以price通过结果。为简单起见,我们在这里使用 1 年。

SQL小提琴 http://sqlfiddle.com/#!17/648ff/11对于这个问题。 (Postgres 9.6)

举个简单的例子,price and peak_earnings for 2010-01-01可以像这样单独计算:

SELECT price
FROM security_data
WHERE date = '2010-01-01'
AND security_id = 'SPX';

SELECT max(earnings) AS min_earnings
FROM bloomberg.security_data
WHERE date >= '2000-01-01'
AND date <= '2010-01-01'
AND security_id = 'SPX';

去做这个per row,我使用以下内容:

SELECT security_id, date, price
     , CASE WHEN date1 >= min_date
            THEN price / NULLIF(max(earnings) FILTER (WHERE date >= date1) OVER w, 0) END AS price_to_peak_earnings
FROM
(
  SELECT record_id, security_id, price, date, earnings
           , (date - interval '1 y')::date AS date1
           , min(date) OVER (PARTITION BY security_id) AS min_date
      FROM   security_data
) d
WINDOW w AS (PARTITION BY security_id);

我相信这里的问题源于使用FILTER,因为它似乎没有按照我想要的方式工作。请注意,在链接的 SQL Fiddle 中,我显示了以下结果FILTER,并且对于每一行peak_earnings and minimum_earnings只是整个数据集的最大值和最小值。他们should是最大/最小值earnings从 1 年前到当前行。

这里发生了什么?我从答案中知道this https://stackoverflow.com/questions/31396434/referencing-current-row-in-filter-clause-of-window-function我不能简单地说出的问题FILTER (WHERE date >= date1 AND date <= current_row.date),那么我缺少什么解决方案吗?我不能使用窗框,因为在任何给定的时间范围内我的行数都不确定,所以我不能只是说OVER (ROWS BETWEEN 365 PRECEDING AND CURRENT ROW)。我可以使用框架吗and过滤器?这可能是一年多以前,然后过滤器可以捕获每个无效日期。我已经尝试过这个但没有成功。


我可以使用框架和过滤器吗?

You can。但两者都有限制:

  • 中的表达式为FILTER子句只能看到它获取值的相应行。无法引用窗口函数计算值的行。所以我没有找到一种方法来制定过滤器that行除非我们做了一个巨大、昂贵交叉连接 - 同一行用于许多不同的计算。或者我们回到LATERAL子查询can引用父行。

  • 另一方面,框架定义根本不允许变量。它需要一个固定的数字,正如您引用的相关答案中所讨论的:

    • 在窗口函数的 FILTER 子句中引用当前行 https://stackoverflow.com/questions/31396434/referencing-current-row-in-filter-clause-of-window-function

这些限制使您的特定查询难以实现。这应该是correct now:

SELECT *
FROM  (
   SELECT record_id, security_id, date, price
        , CASE WHEN do_calc THEN                max(earnings) OVER w1     END AS peak_earnings
        , CASE WHEN do_calc THEN                min(earnings) OVER w1     END AS minimum_earnings
        , CASE WHEN do_calc THEN price / NULLIF(max(earnings) OVER w1, 0) END AS price_to_peak_earnings
        , CASE WHEN do_calc THEN price / NULLIF(min(earnings) OVER w1, 0) END AS price_to_minimum_earnings
   FROM  (
      SELECT *, (date - 365) >= min_date AND s.record_id IS NOT NULL AS do_calc
      FROM  (
         SELECT security_id, min_date
              , generate_series(min_date, max_date, interval '1 day')::date AS date
         FROM  (
            SELECT security_id, min(date) AS min_date, max(date) AS max_date
            FROM   security_data
            GROUP  BY 1
            ) minmax
         ) d
      LEFT   JOIN  security_data s USING (security_id, date)
      ) sub1
   WINDOW w1 AS (PARTITION BY security_id ORDER BY date ROWS BETWEEN 365 PRECEDING AND 1 PRECEDING)
   ) sub2
WHERE  record_id IS NOT NULL 
ORDER  BY 1, 2;

SQL 小提琴。 http://sqlfiddle.com/#!17/b0fd2/2

Notes

  • 问题中没有任何内容表明每个security_id将会有同一天的行。计算最小/最大日期security_id在子查询中minmax给我们最短的时间范围。

  • 计算的时间范围正好是该行当前日期之前的 365 天,并且not包括当前行(ROWS BETWEEN 365 PRECEDING AND 1 PRECEDING)。它通常更有用exclude聚合中的当前行与当前行进行比较。
    我将计算条件调整为同一时间范围,以避免出现极端情况:(date - 365) >= min_date

  • In the fiddle http://sqlfiddle.com/#!17/b0fd2/2,您为每年 1 月 1 日添加 1 行,您可以看到闰年与固定天数 365 天的对比效果。闰年(2001 年、2005 年……)之后窗框是空的。

  • 我正在使用所有子查询,这通常比 CTE 快一点。

  • 可以肯定的是,我们需要包括ORDER BY在框架定义中。我相应地更新了您链接到的旧答案:

    • 在窗口函数的 FILTER 子句中引用当前行 https://stackoverflow.com/questions/31396434/referencing-current-row-in-filter-clause-of-window-function
  • I use w1作为窗口name,“1 年”期间。你可能会添加w2等,并且每个可以有任意天数。如果你需要的话,你毕竟可以适应闰年。甚至可能根据当前日期生成整个查询......

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

窗口函数过滤当前行 的相关文章

随机推荐

  • 如何在 StreamBuilder 中更新 Flutter 卡而不重置状态?

    我让 StreamBuilder 正常工作 1 件事 每次 1 个元素更改时 整个列表都会重置 例如 每张卡都有一个计数器 我希望在不改变屏幕的情况下看到它的加法和减法 我怎样才能做到这一点 这是我的代码 使用完整文件堆栈更新 final
  • Android:如何从 gridview 中删除一个项目,并将剩余的项目随机就位

    背景 我有一个包含 36 个按钮的网格 假设有 6 行和 6 列 编号为 1 到 36 通过 GridView 和自定义适配器一次显示 2 行 网格显示良好 并且所有滚动都正常工作 问题 我希望能够单击一个项目 将其从网格中删除 并将剩余的
  • 从 Qt 5.7 切换到 Qt 5.8 - “代理类型对此操作无效”

    我正在尝试使用 Qt 5 8 重新编译一个与 Qt 5 7 配合良好的网络应用程序 然而 使用Qt 5 8 服务器无法listen int myPort 52000 some accessible port QTcpServer serve
  • 在使用 linq-to-entities 的一对多连接中仅获取一条(最后一条)记录

    我在 linq to entities 中有以下内容 clientprojects from p in this SAPMappingEntities SAP Master Projects join c in this SAPMappin
  • 在 GitHub Actions 中缓存 node_modules

    我有一个 Yarn monorepo 工作区 有 2 个包 后端 Node js TypeScript 和前端 React Typescript package json 已修剪 workspaces backend frontend 我正
  • Xamarin.IOS 上的内存管理如何工作

    我正在尝试了解使用 xamarin ios 并在实际 iOS 设备上运行该应用程序时内存管理的工作原理 我的理解是iOS平台没有垃圾收集器 但是平台使用ARC Automatci Reference Counting 编译后的应用程序真的会
  • Powershell 在 System.Drawing 中使用 .NET .DrawImage

    我正在制作一个工具 可以自动裁剪和定位 无需将图像大小调整为其他图像 我发现this https learn microsoft com en us dotnet api system drawing graphics drawimageu
  • 我正在评估 Google Pub/Sub 与 Kafka。有什么区别? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对kafka的工作不多 但想在GCE中构建数据管道 所以我们想了解 Kafka 与 PUB Sub 基本上我想知道Kafka和Pub
  • 转换为 Func 与新 Func?

    下面两条语句有什么区别吗 他们都工作 if Func
  • 如何在 C# 中为控件添加移动效果?

    我的 C 表单中有一个面板 并且有一个按钮 当我单击按钮时 会显示不可见的面板 相反 我希望面板移入或滑入 例如 当您单击组合框时 下拉列表不会弹出 我希望我的面板像那样显示 我怎样才能做到这一点 窗口动画是 Windows 的内置功能 这
  • 无法传入 lambda 来申请 pandas DataFrame

    我正在尝试将函数应用于 pandas DataFrame 的所有行 实际上只是该 DataFrame 中的一列 我确信这是一个语法错误 但我知道我做错了什么 df col apply lambda x y x y total seconds
  • CLR 项目的智能感知 - 例如没有智能感知系统.Windows.窗体

    我一直在关注一些关于某些内容的两个教程Visual C 基础知识 http www functionx com vccli general introprogramming htm但他们似乎都缺乏有关我如何在 Visual Studio 2
  • Google AppInvites 中断构建

    您的应用程序的一部分build gradle这是 tasks withType com android build gradle tasks PackageApplication pkgTask gt pkgTask jniFolders
  • 如何在v-html中运行脚本

    我从数据库获取嵌入代码 Instagram Twitter 等 如何将它们绑定到 vue 组件 有没有办法在v html中执行脚本标签 简短的回答 你不能 一旦 dom 加载 您的浏览器就会阻止脚本标签的执行 长答案 您可以尝试匹配脚本的
  • 如何保留对 NPM 模块所做的本地更改?

    我已经使用 NPM 拉下了一个节点模块 并将其添加到package json 然而 需要更改模块的一些代码 因为它没有 100 满足我的要求 通常当我使用节点时git我会忽略node modules目录及使用npm install部署到服务
  • CSS - 并排的内联块,宽度为 100%

    我有两个带有文本的块 文本的长度不是恒定的 用户输入 左侧块中包含短文本 但右侧块可能包含非常长的文本 这些块应该并排出现 并且分布在父级恒定宽度的 100 上 不多也不少 简化示例 https jsfiddle net hh6a03cy
  • 在恒定空间和线性时间内向后打印单链表

    我听到一个面试问题 向后打印单链表 在恒定空间和线性时间中 我的解决方案是反转链接列表 然后像这样打印它 还有其他非破坏性的解决方案吗 您已经找到了大部分答案 将链表反转到位 然后将列表遍历回开头以打印它 为了防止它 永久 破坏性 请就地反
  • AtomicBoolean 与同步块

    我试图通过替换一些来减少代码中的线程争用synchronized块与AtomicBoolean 这是一个例子synchronized public void toggleCondition synchronized this mutex i
  • Subversion 和 CVS 中添加自动内容的标签怎么称呼?

    像 log and version 在签入文件时添加数据 我有兴趣查看其他人以及他们可以提供哪些信息 但除非我知道他们叫什么 否则我无法获得太多信息 Subversion 和 CVS 都称它们为Keywords 在这里查看 SVN 手册 h
  • 窗口函数过滤当前行

    这是后续this https stackoverflow com questions 48000013 optimize slow aggregates in lateral join问题 我的查询被改进为使用窗口函数而不是内部的聚合LAT