递归查询中不允许使用聚合函数。有没有其他方法可以编写此查询?

2023-12-31

TL;DR我不知道如何编写在递归部分不使用聚合函数的递归 Postgres 查询。是否有其他方法可以编写如下所示的递归查询?

假设我们有一些运动:

CREATE TABLE sports (id INTEGER, name TEXT);

INSERT INTO sports VALUES (1, '100 meter sprint');
INSERT INTO sports VALUES (2, '400 meter sprint');
INSERT INTO sports VALUES (3, '50 meter swim');
INSERT INTO sports VALUES (4, '100 meter swim');

以及参加这些运动的运动员的一些单圈时间:

CREATE TABLE lap_times (sport_id INTEGER, athlete TEXT, seconds NUMERIC);

INSERT INTO lap_times VALUES (1, 'Alice',  10);
INSERT INTO lap_times VALUES (1, 'Bob',    11);
INSERT INTO lap_times VALUES (1, 'Claire', 12);

INSERT INTO lap_times VALUES (2, 'Alice',  40);
INSERT INTO lap_times VALUES (2, 'Bob',    38);
INSERT INTO lap_times VALUES (2, 'Claire', 39);

INSERT INTO lap_times VALUES (3, 'Alice',  25);
INSERT INTO lap_times VALUES (3, 'Bob',    23);
INSERT INTO lap_times VALUES (3, 'Claire', 24);

INSERT INTO lap_times VALUES (4, 'Alice',  65);
INSERT INTO lap_times VALUES (4, 'Bob',    67);
INSERT INTO lap_times VALUES (4, 'Claire', 66);

我们想要创建一些任意类别:

CREATE TABLE categories (id INTEGER, name TEXT);

INSERT INTO categories VALUES (1, 'Running');
INSERT INTO categories VALUES (2, 'Swimming');
INSERT INTO categories VALUES (3, '100 meter');

并使我们的体育成员成为这些类别:

CREATE TABLE memberships (category_id INTEGER, member_type TEXT, member_id INTEGER);

INSERT INTO memberships VALUES (1, 'Sport', 1);
INSERT INTO memberships VALUES (1, 'Sport', 2);

INSERT INTO memberships VALUES (2, 'Sport', 3);
INSERT INTO memberships VALUES (2, 'Sport', 4);

INSERT INTO memberships VALUES (3, 'Sport', 1);
INSERT INTO memberships VALUES (3, 'Sport', 4);

我们想要一个包含其他类别的“超级”类别:

INSERT INTO categories VALUES (4, 'Running + Swimming');

INSERT INTO memberships VALUES (4, 'Category', 1);
INSERT INTO memberships VALUES (4, 'Category', 2);

现在来了棘手的一点。

我们希望根据运动员在每项运动中的单圈时间进行排名:

SELECT sport_id, athlete,
  RANK() over(PARTITION BY sport_id ORDER BY seconds)
FROM lap_times lt;

但我们也想在品类层面做到这一点。当我们这样做时,运动员的排名应该基于他们在该类别中所有运动中的平均排名。例如:

Alice is 1st in 100 meter sprint and 3rd in 400 meter sprint
  -> average rank: 2

Bob is 2nd in 100 meter sprint and 1st in 400 meter sprint
  -> average rank: 1.5

Claire is 3rd in 100 meter sprint and 2nd in 400 meter sprint
  -> average rank: 2.5

Ranking for running: 1st Bob, 2nd Alice, 3rd Claire

对于“超级”类别,运动员的排名应基于其跨类别的平均排名,而不是这些类别中的基础运动。即它应该只考虑它的直接子项,而不是扩展到所有运动。

我尽力编写了一个查询来计算这些排名。这是一个递归查询,从底部的体育项目开始,向上遍历会员资格,计算类别和“超级”类别的排名。这是我的查询:

WITH RECURSIVE rankings(rankable_type, rankable_id, athlete, value, rank) AS (
  SELECT 'Sport', sport_id, athlete, seconds, RANK() over(PARTITION BY sport_id ORDER BY seconds)
  FROM lap_times lt

  UNION ALL

  SELECT 'Category', category_id, athlete, avg(r.rank), RANK() OVER (PARTITION by category_id ORDER BY avg(r.rank))
  FROM categories c
  JOIN memberships m ON m.category_id = c.id
  JOIN rankings r ON r.rankable_type = m.member_type AND r.rankable_id = m.member_id
  GROUP BY category_id, athlete
)
SELECT * FROM rankings;

但是,当我运行它时,我收到以下错误:

ERROR: aggregate functions are not allowed in a recursive query's recursive term

这是由于avg(r.rank)在查询的递归部分。 Postgresql 不允许在查询的递归部分调用聚合函数。有没有其他方法可以写这个?

如果我交换avg(r.rank), RANK() ...出去为了NULL, NULL执行查询,结果对于体育运动来说看起来是正确的,并且包含类别的预期行数。

我考虑过尝试使用嵌套查询将递归展开到两级或三级,因为这对我的用例来说很好,但我想在尝试之前先在这里问一下。

另一种选择可能是更改架构,使其灵活性降低,从而使体育运动不能属于多个类别。我不确定在这种情况下查询会是什么样子,但它可能更简单?

预先感谢,我真的很感激。


这并不漂亮,但我找到了解决方案:

WITH RECURSIVE rankings(rankable_type, rankable_id, athlete, value, rank) AS (
  SELECT 'Sport', sport_id, athlete, seconds, RANK() over(PARTITION BY sport_id ORDER BY seconds)
  FROM lap_times lt

  UNION ALL

  SELECT 'Category', *, rank() OVER(PARTITION by category_id ORDER BY avg_rank) FROM (
    SELECT DISTINCT category_id, athlete, avg(r.rank) OVER (PARTITION by category_id, athlete) AS avg_rank
    FROM categories c
    JOIN memberships m ON m.category_id = c.id
    JOIN rankings r ON r.rankable_type = m.member_type AND r.rankable_id = m.member_id
  ) _
)
SELECT * FROM rankings;

在查询的递归部分,而不是调用GROUP BY并计算avg(r.rank),我使用在相同列上分区的窗口函数。这与计算平均排名具有相同的效果。

一个缺点是这种计算发生的次数超出了必要的次数。如果我们可以GROUP BY then avg(r.rank),这会比avg(r.rank) then GROUP BY.

由于嵌套查询的结果现在有重复项,我正在使用DISTINCT过滤掉这些,然后外部查询计算RANK()每个项目的所有运动员category_id基于这些平均值。

我仍然很想听听是否有人知道更好的方法来做到这一点。谢谢

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

递归查询中不允许使用聚合函数。有没有其他方法可以编写此查询? 的相关文章

  • Alembic 无法识别 False 默认值

    在维护 SQLAlchemy 数据模型并利用 alembic 进行版本控制时 我所做的以下代码更改导致了空修订 some column Column Boolean nullable False default False 以前是 some
  • 将数组文字传递给 PostgreSQL 函数

    我有一个包含 select 语句的 Postgres 函数 我需要使用包含字符串值数组的传入变量添加条件 CREATE OR REPLACE FUNCTION get questions vcode text RETURN return v
  • Camel Sql 大型数据集的消费者性能

    我正在尝试在 Ignite 缓存中缓存一些静态数据 以便更快地查询 因此我需要从 DataBase 读取数据 以便将它们插入到缓存集群中 但是行数约为 300 万 通常会导致 OutOfMemory 错误 因为 SqlComponent 试
  • SQL Server、ISABOUT、加权项

    我试图弄清楚加权项在 SQL SERVER 的 ISABOUT 查询中是如何工作的 这是我目前所在的位置 每个查询返回以下行 查询 1 权重 1 初始排名 SELECT FROM CONTAINSTABLE documentParts ti
  • 一组记录中某些值相同的唯一约束

    DBMS MS Sql Server 2005 标准版 我想创建一个表约束 以便只有一个记录在表的子集中具有特定值 其中行共享特定列中的值 这可能吗 Example 我的 myTable 中有一些记录 其中有一个非唯一的外键 fk1 以及一
  • SQL分组和总结

    我的表如下所示 income date productid invoiceid customerid 300 2015 01 01 A 1234551 1 300 2016 01 02 A 1234552 1 300 2016 01 03
  • 动态/条件 SQL 连接?

    我在 MSSQL 表 TableB 中有数据 其中 dbo tableB myColumn 在特定日期后更改格式 我正在做一个简单的连接到该表 Select dbo tableB theColumnINeed from dbo tableA
  • MySQL:用户对数据库的访问被拒绝

    我正在尝试在 Heroku 上的远程 SQL 服务器上创建一个数据库 clearDB 我与此联系 mysql host lt
  • 显示多个表的账户余额

    我有以下两个表 其中存储有关贷记和借记记录的信息 couponCr 表包含 voucherType voucherPrefix voucherNo crparty cramount SALES S 1 1 43000 SALES S 2 1
  • Docker-compose v3 不持久保存 postgres 数据库

    在 docker compose v3 容器关闭并重新启动后 我很难保留 postgres 数据 这似乎是一个常见问题 但经过大量搜索后我无法找到有效的解决方案 我的问题与这里类似 如何使用卷将数据保存在 dockerized postgr
  • 单向关系和双向关系的区别

    我想知道这两个词是什么意思 我遇到他们是在教义的文档 http www doctrine project org documentation manual 2 0 en association mapping 但我不明白他们的意思 这与常见
  • 用于从深层嵌套列表/元组中提取元素的递归函数

    我想编写一个从深层嵌套元组和列表中提取元素的函数 假设我有这样的东西 l THIS THAT a b c THAT d e f 我想要一个没有 这个 和 那个 的简单列表 list a b c d e f 这是我到目前为止所拥有的 def
  • PDO 库比本机 MySQL 函数更快吗?

    我已经阅读了几个与此相关的问题 但我担心它们可能已经过时 因为自这些问题得到解答以来 更新版本的 PDO 库已经发布 我编写了一个 MySQL 类 它构建查询并转义参数 然后根据查询返回结果 目前这个类正在使用内置的mysql函数 我很清楚
  • SQL:将现有列设置为 MySQL 中的主键

    我有一个包含 3 列的数据库 id name somethingelse 该表没有设置索引 我收到 未定义索引 在 phpmyadmin 中id 是一个 7 位字母数字值 每行都是唯一的 我想将 Drugid 设置为主键 索引 我不知道有没
  • 删除重复的 SQL 记录以允许唯一键

    我在 MYSQL 数据库中有一个表 销售 该表理应强制执行唯一约束以防止重复 事实证明 首先删除欺骗并设置约束有点棘手 表结构 简化 id 唯一 autoinc 产品编号 目标是强制product id 的唯一性 我想要应用的重复数据删除策
  • 获取 Postgres 数据库中每个表的行数

    获取数据库中所有表的行数的最有效方法是什么 我正在使用 Postgres 数据库 结果示例 table name row count some table 1 234 foobar 5 678 another table 32 如果您想要特
  • 如何使用 SQL Server 查询对“版本号”列进行排序

    我想知道我们当中的 SQL 天才是否可以向我伸出援助之手 我有一个专栏VersionNo在表中Versions包含 版本号 值 例如 VersionNo 1 2 3 1 1 10 3 1 1 4 7 2 etc 我正在寻找对此进行排序 但不
  • sqlite 插入表中 select * from

    我需要在 Android 应用程序中将数据从一个表移动到另一个表 我想使用以下sql insert into MYTABLE2 select id STATUS risposta DATETIME now data ins from MYT
  • 尝试使用 Rails 和 PostgreSQL 生成模型时,命令挂起且没有错误

    使用该命令时 rails generate model Event name string 什么也没发生 我必须按 CTRL c 我使用的版本是 红宝石 2 1 1p76 导轨4 1 0 PostgreSQL 9 3 4 Mac OS X
  • 使用 SQL 确定子网掩码的 cidr 值

    我想找到一种方法来执行 SQL 查询 该查询将计算存储在数据库中的子网掩码的 cidr 位表示 例如 我在数据库中存储了 255 255 255 0 或其十进制值 4294967040 我想通过查询进行选择并返回 24 表示 我已经执行了类

随机推荐

  • 获取 MongoDB 中更新的文档

    我需要得到 id更新文档的 Mongo ObjectID 为此 我想获取更新的文档 我怎么才能得到它 我试过这个 collection update oldData newData function err doc console log
  • 如何获取Google云存储的授权令牌

    我正在尝试集成 Google 云存储 API 以将我所有的网络应用程序上传传输到 google 云存储 根据文档 我每次发出新请求时都需要传递授权标头 但无法在哪里获取授权令牌 我非常努力地检查了很多 Git 存储库和 StackOverf
  • 从货币代码获取 CultureInfo?

    我需要获取不同货币代码的 System Globalization CultureInfo 示例 欧元 英镑 美元 目前 我正在基于这 3 个字母货币代码的 switch 语句中执行以下操作 显然这不是执行此操作的方法 var ci new
  • Rails:我如何需要 ActiveSupport 的救援_from 方法?

    我有这个代码application controller Method to capture and handle all exceptions rescue from Exception do ex Rails logger debug
  • 如何获取 Windows 应用商店应用程序中正在执行的程序集版本信息?

    在将应用程序移植到 Windows 应用商店时 我注意到 NETCore Framework 不包括 System Reflection Assembly GetExecutingAssembly 我用它来获取版本信息以显示在菜单屏幕上 是
  • Rails 3.1、资产管道和 IE 6 & 7 处于生产模式 - 某些 CSS 和 js 未正确加载

    在生产模式下尝试我的 Rails 3 1 应用程序 Debian 6 Ruby 1 9 2 Passenger 我使用 IE 6 和 IE 7 进行了尝试 但某些资源未正确加载 在开发模式下一切正常 一些 css 和 js 未正确加载 所有
  • 如何在 Ruby 中的哈希列表中提取每个键的更大值

    我可以想象有一种简单的方法可以做到这一点 而不是使用许多变量和状态 我只想获得哈希列表中每个键的最高值 例如 1 gt 19 4 1 gt 12 4 2 gt 29 4 3 gt 12 4 2 gt 39 4 2 gt 59 4 Resul
  • 无法打开文件“glew32.lib”

    我已经下载了 glew 1 9 0 zip 在 C glew 1 9 0 build vc6 和 C glew 1 9 0 build vc10 下构建了项目 并且在将 Visual Studio 的路径设置为后无法构建glew inclu
  • Java字节码解释器

    我知道java程序首先被编译并生成与平台无关的字节码 但我的问题是 为什么这个字节码在下一阶段被解释而不是被编译 即使编译通常比解释更快 你是在自问自答 字节码是平台无关的 如果执行编译后的代码 则它不会在每个操作系统上运行 这就是 C 的
  • 警报对话框背景主题/颜色

    我想设置AlertDialogue主题或change背景颜色 虽然我知道它有一个默认主题 但在不同的版本中我得到了不同的主题 所以我想为所有版本修复它 或者简单地将背景颜色更改为白色 NonNull public Dialog onCrea
  • 从 PlaceAutocompleteFragment android (Google Places API) 获取国家/地区代码

    在 Android 版 Google Places API 中 我使用 PlaceAutocompleteFragment 来显示城市 国家 这里正在获取地址 名称 placeId 等 Place对象仅包含这些字段 Override pub
  • 如何使用系统签名密钥对我的应用程序进行签名?

    我需要创建一个 Robotium 应用程序 该应用程序将使用 设置 应用程序从菜单 设置 gt 无线和网络 gt Wi Fi 打开 关闭 WIFI 我设法找到了一些示例代码here http code google com p roboti
  • 如何缩放 SVG 路径

    我尝试缩放 svg 路径之类的元素 但缩放对于 div 元素工作正常 不适用于 svg 路径元素 我在下面附上了我的代码 有什么建议吗
  • ngModel 自定义 ValuesAccessor

    关于 ngModel 和 DI 的高级问题 正如我在这里看到的 https github com angular angular blob 2 0 0 beta 1 modules angular2 src common forms dir
  • R:按名称组合嵌套列表元素

    假设我有一个列表结构 其中有data frames嵌套在每个元素中 l lt list A list D data frame V1 seq 3 V2 LETTERS 1 3 E data frame V1 seq 3 V2 LETTERS
  • 如何在 Forth 中创建数组?

    我知道 这个问题过去经常被问到 也许之前的 Stack Overflow 帖子中已经给出了这些信息 但学习 Forth 是一项非常复杂的任务 重复有助于理解串联编程语言相对于 C 等替代语言的优势 我从 Forth 教程中学到的是 Fort
  • 基于内容的节流

    我想知道Camel是否可以根据交换的内容进行限制 情况如下 我必须通过soap 调用网络服务 其中 发送到该webservice的参数中有一个customerId 问题是 如果给定的 customerId 每分钟有超过 1 个请求 则 We
  • jQuery keyup keyCode 在 Opera 中不起作用

    Opera 浏览器是否有可能忽略 keyCode 40 向下箭头 test keyup function e body append e keyCode 测试它 http www jsfiddle net V9Euk 454 http ww
  • 如何将已知的接口属性与自定义索引签名结合起来?

    如何键入一个可以同时具有几个属性的对象声明的可选属性 e g hello string moo boolean 以及自定义属性 必须是函数 例如 custom string v any gt boolean 这就是我想看到的 例如 cons
  • 递归查询中不允许使用聚合函数。有没有其他方法可以编写此查询?

    TL DR我不知道如何编写在递归部分不使用聚合函数的递归 Postgres 查询 是否有其他方法可以编写如下所示的递归查询 假设我们有一些运动 CREATE TABLE sports id INTEGER name TEXT INSERT