窗口函数过滤当前行

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(使用前将#替换为@)

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

  • 将两行中相似的列数据合并到一行中

    我的查询结果具有以下特征 LIDCode Total Domain Region VSE Version AB02 15 GLOBAL CANLA 0 6943 AB02 5925 CENTRE STREET SW 31 GLOBAL CA
  • 如何查找 PostgreSQL 数据库的上次更新时间?

    我正在使用一个批量更新的 postgreSQL 数据库 我需要知道数据库 或数据库中的表 上次更新或修改的时间 两者都可以 我看到 postgreSQL 论坛上有人建议使用日志记录并查询日志 这对我不起作用 因为我无法控制客户端代码库 你可
  • 模式更新后 jOOQ 生成的类的运行时验证?

    我用org jooq util DefaultGenerator在构建过程中生成 jOOQ 类来表示我的数据库模式 当应用程序运行时 架构预计会在应用程序不知情的情况下发生更改 此类更改可能与已生成的代码兼容 也可能不兼容 如何在运行时检测
  • postgres 有 CLOSEST 运算符吗?

    我正在寻找这样的东西 给定一个表格 id number 1 7 2 1 25 3 1 01 4 3 0 查询SELECT FROM my table WHEREnumberCLOSEST 1 将返回第 3 行 我只关心数字 现在我有一个程序
  • 插入多行并返回主键时 Sqlalchemy 的奇怪行为

    插入多行并返回主键时 我注意到一些奇怪的事情 如果我在 isert 查询中添加使用参数值 我会得到预期的行为 但是当将值传递给游标时 不会返回任何内容 这可能是一个错误还是我误解了什么 我的sqlachemy版本是0 9 4 下面如何重现错
  • 数据库错误:值对于类型字符变化来说太长(100)

    我有一个 Django 网站 运行我们几年前在内部构建的迷你 CMS 它使用 postgresql 保存简单的标题和一段文本时 出现以下错误 value too long for type character varying 100 奇怪的
  • sql查询将两列与一列连接起来

    我在 MS Access 2010 中有 2 个表 如下所示 USERS u id u name LOAN l id l from ref users u id l to ref users u id l amount Users u id
  • 如何在 sqlalchemy 中创建基于文字的查询?

    我创建了一个函数来创建表达式 def test operator1 operation operator2 return literal column operator1 op operation operator2 现在当我用 test
  • 如何有效地从 DB2 表中删除所有行

    我有一个大约有 50 万行的表 我想删除所有行 如果我做简单的delete from tbl 事务日志已满 我不关心这种情况下的事务 无论如何我都不想回滚 我可以删除许多事务中的行 但是有更好的方法吗 如何有效地从 DB2 中的表中删除所有
  • SPARK SQL - 当时的情况

    我是 SPARK SQL 的新手 SPARK SQL 中是否有相当于 CASE WHEN CONDITION THEN 0 ELSE 1 END 的内容 select case when 1 1 then 1 else 0 end from
  • SQLite HAVING 比较错误

    我有一个测试 SQLite 表 用于存储带有值的报告数据 CREATE TABLE IF NOT EXISTS test fact daily revenue date TEXT revenue NUMERIC product TEXT I
  • 如何使用PostGIS将多边形数据转换为线段

    我在 PostgreSQL PostGIS 中有一个多边形数据表 现在我需要将此多边形数据转换为其相应的线段 谁能告诉我如何使用 PostGIS 查询进行转换 提前致谢 一般来说 将多边形转换为线可能并不简单 因为没有一对一的映射 http
  • 如何在不运行 PostgreSQL 服务器的情况下初始化 PostgreSQL 数据库

    在初始化脚本中 我想初始化 PostgreSQL 目录 但在此阶段不需要 也不希望 正在运行的 PostgreSQL 服务器 如果我只是创建集群 作为用户postgres initdb D 但是 我还需要创建 PostgreSQL 角色 创
  • SQL 删除表并重新创建并保留数据

    在我们最初的设计中 我们搞砸了表中的外键约束 现在表已充满数据 我们无法在不删除表中所有记录的情况下更改它 我能想到的唯一解决方案是创建一个备份表并将所有记录放在那里 然后删除所有记录 更改表并开始将它们添加回来 还有其他 更好 的想法吗
  • Mysql 中 UNION 子句的替代方案

    我有两张桌子 表 a 表 b table a ID 1 2 3 4 5 7 table b ID 2 3 4 5 6 我必须得到这样的输出而无需UNION命令 ID 1 2 3 4 5 6 7 注意 我有一个联合解决方案 select fr
  • 在sqlite SQL语句中与order by子句结合使用limit

    下面的两条 SQL 语句总是会产生相同的结果集吗 1 SELECT FROM MyTable where Status 0 order by StartTime asc limit 10 2 SELECT FROM SELECT FROM
  • 如何在 PostgreSQL 中使用具有多个值的 SQL LIKE 条件?

    有没有更短的方法来查找多个匹配项 SELECT from table WHERE column LIKE AAA OR column LIKE BBB OR column LIKE CCC 这个问题适用于 PostgreSQL 9 1 但如
  • 使用 where 进行 select 语句时,HSQLDB 用户缺乏权限或未找到对象错误

    我的数据库使用 SQuirrel SQL 客户端版本 3 5 3 和 HSQLDB 我已经能够为其指定相应的驱动程序 内存中 并创建一个别名 我创建了一个表 CREATE TABLE ENTRY NAME VARCHAR 100 NOT N
  • 在 PostgreSQL 中使用月份名称排序

    我有一个表 其中有一个字段 Month Name 它包含月份的名称 我想按月份名称排序 不是按字母顺序 而是按实际顺序 例如一月 二月等 如何使用 PostgreSQL 实现此操作 有什么方法可以将月份名称转换为其数值吗 id billed
  • MySQL 按重复项从上到下排序

    我有一个lammer问题 因为我不是mysql专业人士 我有类似的字段 id color 1 red 2 green 3 yellow 4 green 5 green 6 red 我想按重复项进行分组 最常见的重复项先进行分组 所以应该这样

随机推荐

  • 如何在 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