如何编写具有这种不寻常匹配标准的联接?

2024-05-25

我想要“左连接”一个表,以便值不仅连接到匹配行,而且还连接到任何后续的非匹配行,直到下一个匹配行。换句话说,我想用之前的非空值来填充空值。

样本数据和期望结果:

Table x:

 id 
----
  1
  2
  3
  4
  5

Table y:

 id | val 
----+-----
  1 | a
  4 | b

的结果select x.id, y.val from x left join y on x.id=y.id order by x.id;:

 id | val 
----+-----
  1 | a
  2 | 
  3 | 
  4 | b
  5 | 

期望的结果:

 id | val 
----+-----
  1 | a
  2 | a
  3 | a
  4 | b
  5 | b

Indices

创建索引x.id and y.id- 如果这些是您的主键,您可能已经拥有了。
多列索引也可能有所帮助,尤其是仅索引扫描 https://wiki.postgresql.org/wiki/Index-only_scans在 9.2+ 页中:

CREATE INDEX y_mult_idx ON y (id DESC, val)

然而,在我的测试中,一开始并没有使用这个索引。必须添加(否则毫无意义)val to ORDER BY让查询规划器相信排序顺序是匹配的。查看查询3.

该指数在这种综合设置中几乎没有什么区别。但对于具有更多列的表,检索val表格变得越来越昂贵,使得“覆盖”指数更具吸引力。

Queries

1)简单

SELECT DISTINCT ON (x.id)
       x.id, y.val
FROM   x
JOIN   y ON y.id <= x.id
ORDER  BY x.id, y.id DESC;

SQL 小提琴。 http://sqlfiddle.com/#!12/38903/7

该技术的更多解释DISTINCT在这个相关的答案中:

  • 选择每个 GROUP BY 组中的第一行? https://stackoverflow.com/questions/3800551/select-first-row-in-each-group-by-group/7630564#7630564

我运行了一些测试,因为我怀疑第一个查询不能很好地扩展。对于小表来说速度很快,但是对于较大的表则不好。 Postgres 不会优化该计划,而是从(有限的)交叉连接开始,成本为O(N²).

2) Fast

这个查询仍然相当简单并且扩展性非常好:

SELECT x.id, y.val
FROM   x
JOIN  (SELECT *, lead(id, 1, 2147483647) OVER (ORDER BY id) AS next_id FROM y) y
       ON  x.id >= y.id
       AND x.id <  y.next_id
ORDER  BY 1;

窗口函数lead() http://www.postgresql.org/docs/current/interactive/functions-window.html是有帮助的。我利用该选项提供默认值来覆盖最后一行的极端情况:2147483647 is the 最大可能的整数 http://www.postgresql.org/docs/current/interactive/datatype-numeric.html。适应您的数据类型。

3)非常简单并且几乎一样快

SELECT x.id
     ,(SELECT val FROM y WHERE id <= x.id ORDER BY id DESC, val LIMIT 1) AS val
FROM   x;

通常情况下,相关子查询往往会很慢。但是这个可以只从(覆盖)索引中选择一个值,并且在其他方​​面非常简单,因此可以竞争。

额外的ORDER BY item val(粗体强调)似乎毫无意义。但添加它可以让查询规划者相信使用多列索引是可以的y_mult_idx从上面开始,因为排序顺序匹配。请注意

使用 y_mult_idx 仅索引扫描..

in the EXPLAIN output.

测试用例

经过激烈的辩论和多次更新后,我收集了迄今为止发布的所有查询,并制作了一个测试用例以进行快速概述。我只使用 1000 行,因此 SQLfiddle 不会因较慢的查询而超时。但前 4 个(Erwin 2、Clodoaldo、a_horse、Erwin 3)在我所有的本地测试中都是线性扩展的。 再次更新以包含我的最新添加内容,现在改进格式和按性能排序:

大 SQL 小提琴比较性能。 http://sqlfiddle.com/#!12/6d7e1/4

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

如何编写具有这种不寻常匹配标准的联接? 的相关文章

随机推荐

  • Mysql 更快的 INSERT

    好的 我有大约 175k 个 INSERT 语句 相当大的 INSERT 语句 例如 INSERT INTO gast ID Identiteitskaartnummer Naam Voornaam Adres Postcode Stad
  • R 使用 dplyr 将列移动到最后

    对于 data frame 来说n列 我希望能够从任何列移动列1 n 1 位置 成为第 n 列 即非最后一列成为最后一列 我也想使用dplyr 我想这样做而不是简单地键入所有列的名称 例如 data lt data frame a 1 5
  • Karma 测试报告运行速度快,但实际上运行速度慢

    最好的解释是a video https youtu be Zwwi01JuPrQ 或参见下面的 gif 您会注意到 Karma 进度报告器报告测试只需要几毫秒 但显然需要相当长的时间 我在推特上提到了这一点 https twitter co
  • 在 Codeigniter 中显示来自连接的数据

    我正在使用简单的联接从两个数据库中提取数据 这是模型中的连接 function com control this gt db gt select this gt db gt from comments this gt db gt join
  • 使用 JPA 存储库保留 Spring Batch ItemWriter 的问题

    我对春季批次有疑问ItemWriter它依赖于 JPA 存储库来更新数据 这里是 Component public class MessagesDigestMailerItemWriter implements ItemWriter
  • 如何修改 edmx 的默认代码生成策略?

    我想修改默认的代码生成策略 该怎么做 我只是想修改类名 lt code Escape container gt to Entities并将默认连接字符串更改为name Default 我不想为该项目创建模板文件 我想编辑它以便它可以在全球范
  • 有条件减少 CUDA

    我需要总结一下100000值存储在数组中 但带有条件 有没有办法在 CUDA 中做到这一点以快速产生结果 任何人都可以发布一个小代码来做到这一点吗 我认为 要执行条件约简 您可以直接将条件引入为乘法0 假 或1 真 加数 换句话说 假设您希
  • win10、iis 10无法启动、w3svc服务启动失败

    IIS 已停止 无法启动 当我检查服务时 w3svc的依赖项都在运行 但无法启动w3svc C Users lust4 sc qc W3SVC SC QueryServiceConfig Success SERVICE NAME W3SVC
  • Python,质数检查器[重复]

    这个问题在这里已经有答案了 你好 我正在创建一个函数来检查一个数字是否是素数 但它告诉我 9 是一个素数 def eprimo num if num lt 2 return False if num 2 return True else f
  • API级别29 Intent.ACTION_GET_CONTENT从下载文件夹返回错误的ID

    我正在尝试查找从文件选择器意图返回的 URI 的完整文件路径 我从互联网下载了一张图像 该图像保存在浏览器默认下载文件夹中 问题是 DocumentsContract getDocumentId content describer 返回的
  • 找到帖子链接、每个标签对应的相关标签并在用户级别进行回答

    继续我之前的question https stackoverflow com questions 60967044 retrieve count of total no of answers corresponding to each ta
  • 如何将背景颜色(或自定义 css 类)应用于网格中的列 - ExtJs 4?

    看起来应该很简单 但我根本无法完成此任务 我什至不需要动态完成它 例如 假设我有一个简单的 2 列网格设置 如下所示 columns header USER dataIndex firstName width 70 cls red head
  • 编写 CherryPy 装饰器以进行授权

    我有一个cherrypy应用程序 在某些视图上我想开始只允许某些用户查看它们 并将其他任何人发送到需要授权的页面 有没有办法使用自定义装饰器来做到这一点 我认为这将是最优雅的选择 这是我想做的一个基本示例 class MyApp autho
  • 在浏览器中读取wsdl文件

    当我尝试在浏览器中打开 WSDL 文件 http localhost something file wsdl 时 我被提议下载该文件 但我希望能够在浏览器中以 XML 字符串 形式查看 而不是下载 谢谢 如果您的服务器未发送 WSDL 文件
  • Prometheus scrape_timeout的使用

    在普罗米修斯配置中 我有以下规格的工作 job name name of my job scrape interval 5m scrape timeout 30s metrics path metrics scheme http 创建指标的
  • DropDownList 列表中的项目

    谁能告诉我在下拉列表中添加所有项目的最短方法List
  • C++头文件问题

    我在处理类时尝试了一些 C 代码 这个问题出现在我身上 并且让我有点烦恼 我创建了一个包含类定义的头文件和一个包含实现的 cpp 文件 如果我在不同的 cpp 文件中使用此类 为什么要包含头文件而不是包含类实现的 cpp 文件 如果我包含类
  • JavaScript 数组中的空项和未定义项有什么区别? [复制]

    这个问题在这里已经有答案了 考虑以下 JavaScript 代码 在节点 REPL 中 gt let a new Array 10 undefined gt a lt 10 empty items gt gt a map e gt 1 lt
  • JList 类型不采用参数类型

    当我尝试编译一些代码时 我不断收到这些错误 CCC java 21 type javax swing JList does not take parameters JList
  • 如何编写具有这种不寻常匹配标准的联接?

    我想要 左连接 一个表 以便值不仅连接到匹配行 而且还连接到任何后续的非匹配行 直到下一个匹配行 换句话说 我想用之前的非空值来填充空值 样本数据和期望结果 Table x id 1 2 3 4 5 Table y id val 1 a 4