首页 > 解决方案 > PostgreSQL 可以返回一个值列表,后面的值会覆盖前面的值吗?

问题描述

下表表示给定文件许可的决策事件。

我想以该文件的许可证列表结束。如果事件的 Removed 列是 False,则添加一个许可证,但每个文件的每个许可证不超过一个。如果事件的 Removed 列为 True,则之前为特定许可证添加的所有事件都将被推翻。稍后发生的事件优先于之前的事件。

对于以下事件,我想返回 [A, B] 的列表。许可证 A 有事件 add、remove、add,所以它被返回。许可证 B 有事件添加,添加,所以它被返回,但不重复。许可证 C 具有事件添加、添加、删除,因此它不会被删除,因为后者的删除会使两个添加事件无效。

这可以通过 PostgreSQL 查询来实现,还是我需要事后处理数据?

+------+---------+---------+
| Time | License | Removed |
+------+---------+---------+
|    1 | A       | False   |
|    2 | A       | True    |
|    3 | A       | False   |
|    4 | B       | False   |
|    5 | B       | False   |
|    6 | C       | False   |
|    7 | C       | False   |
|    8 | C       | True    |
+------+---------+---------+

标签: sqlpostgresqlselectgreatest-n-per-group

解决方案


您可以为此使用聚合:

select license
from t
group by license
having max(time) = max(time) filter (where not removed);

having条款正在检查许可证的最长时间是否未被“删除”。

这三个答案都很合理。一般来说,distinct on在 Postgres 中比row_number()获取一行更可取。如果您对子查询有严格的反感,我会提供这个。


推荐阅读