【发布时间】:2021-02-19 16:02:05
【问题描述】:
(请耐心等待一位自学成才但对 postgres 很着迷的初学者:)
在 POSTGRES 10 中,我提出了一个表格来跟踪编辑和归档照片文件夹的进度。这个进度是按顺序步骤来衡量的,这些步骤通过 foreign_key 链接到另一个表,该表基本上声明 0 =“open”,1 =“work”,2 =“done”。因此,我使用数值来引用这些状态。
为了简单起见,这里是带有一些演示数据的最重要的列:
folder_name | archive_status | step_01 | step_02 | step_03 | ...
----------------------------------------------------------------------------
john | * | 0 | 2 | 0 | ...
paul | * | 0 | 0 | 2 | ...
george | * | 2 | 1 | 0 | ...
ringo | * | 0 | 2 | 0 | ...
想要的结果应该是这样的:
folder_name | archive_status | step_01 | step_02 | step_03 | ...
----------------------------------------------------------------------------
john | step_02 | 0 | 2 | 0 | ...
paul | step_03 | 0 | 0 | 2 | ...
george | step_01 | 2 | 1 | 0 | ...
ringo | step_02 | 0 | 2 | 0 | ...
我的两个问题是:
- 考虑到我的“步骤”顺序,我想过滤“最高”排名的一个(从左到右)。所以在上面的例子中,“john”已经达到了step_02”,“paul 已经达到了step_03”等等。(请注意,“george ... step_02 = 1”等其他值与此无关。)
- 在更新任何值时,我无法在同一个表中完成此操作 - 我是否必须使用 FUNCTION 或 VIEW 或 TRIGGER(或它们的组合)?
我尝试使用聚合函数 https://www.postgresql.org/docs/10/tutorial-agg.html 来处理它,但我有点卡住了,因为我不需要多个输入行,而是在一行中过滤多个列。
--- 更新:新问题---
抱歉,我的初始演示数据不够清晰,这些列更像是一个进度跟踪器,实际上这些列中的每个单元格都可以显示任何值。 (这是答案中的原始解决方案失败的地方,因为如果一行中有两个相同的“最高”值,它将使用第一个出现的值。)所以 SQL 查询应该找到最右边的列,以便说话。当然,我可以在这里想出一些巧妙的“分数计算”,但事实上,使用当前的“矩阵式”设计,事情会容易得多。
同样,根据值 (step_xx) 的 期望结果 (archive_status) 将是:
folder_name | archive_status | step_01 | step_02 | step_03
--------------------------------------------------------------------
john | step_02 | 2 | 2 | 0
paul | step_03 | 1 | 1 | 2
george | step_01 | 2 | 1 | 1
ringo | step_02 | 2 | 2 | 1
【问题讨论】:
-
更好的数据模型将状态存储在单独的行而不是单独的列中。
标签: sql postgresql case greatest-n-per-group