PostgreSQL return 可以用后一个值覆盖前一个值的值列表吗?
Can PostgreSQL return a list of values with latter values overwriting previous ones?
下面的 table 代表给定文件的许可决定事件。
我想以文件的许可列表结束。如果事件的 Removed 列为 False,则添加一个许可证,但每个文件的每个许可证不超过一个。如果事件的 Removed 列为 True,则推翻该特定许可证的所有先前添加事件。稍后发生的事件优先于之前发生的事件。
对于下面的事件,我想要 return [A, B] 的列表。许可证 A 有事件添加、删除、添加,因此它是 returned。许可证 B 有事件添加、添加,因此它被 returned,但没有被复制。许可证 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 |
+------+---------+---------+
您可以在子查询中使用 distinct on
来过滤每个许可证的最后一条记录,然后过滤掉那些被删除的记录:
select license
from (select distinct on (license) t.* from mytable t order by license, time desc) t
where not removed
如果我理解正确,您希望每个许可证都有 last 事件。如果您知道 window 函数的工作原理,这将非常简单:您可以使用 windows 对 table 进行分区,然后通过排序等在每个 window 内部进行操作。在这种情况下,您想要对许可证进行分区,然后按时间排序(降序),最后 select 每个 window:
的最新条目
SELECT "License", "Removed" FROM (
SELECT *, rank() OVER (PARTITION BY "License" ORDER BY "Time" DESC)) X
WHERE rank = 1
如果您想更好地理解它是如何工作的,请尝试自己执行内部 SELECT
。
您可以为此使用聚合:
select license
from t
group by license
having max(time) = max(time) filter (where not removed);
having
子句正在检查许可证的最长时间是否为 "removed"。
这三个答案都很有道理。一般来说,distinct on
在 Postgres 中比 row_number()
更适合获取一行。如果你对子查询有严格的反感,我提供这个。
下面的 table 代表给定文件的许可决定事件。
我想以文件的许可列表结束。如果事件的 Removed 列为 False,则添加一个许可证,但每个文件的每个许可证不超过一个。如果事件的 Removed 列为 True,则推翻该特定许可证的所有先前添加事件。稍后发生的事件优先于之前发生的事件。
对于下面的事件,我想要 return [A, B] 的列表。许可证 A 有事件添加、删除、添加,因此它是 returned。许可证 B 有事件添加、添加,因此它被 returned,但没有被复制。许可证 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 |
+------+---------+---------+
您可以在子查询中使用 distinct on
来过滤每个许可证的最后一条记录,然后过滤掉那些被删除的记录:
select license
from (select distinct on (license) t.* from mytable t order by license, time desc) t
where not removed
如果我理解正确,您希望每个许可证都有 last 事件。如果您知道 window 函数的工作原理,这将非常简单:您可以使用 windows 对 table 进行分区,然后通过排序等在每个 window 内部进行操作。在这种情况下,您想要对许可证进行分区,然后按时间排序(降序),最后 select 每个 window:
的最新条目SELECT "License", "Removed" FROM (
SELECT *, rank() OVER (PARTITION BY "License" ORDER BY "Time" DESC)) X
WHERE rank = 1
如果您想更好地理解它是如何工作的,请尝试自己执行内部 SELECT
。
您可以为此使用聚合:
select license
from t
group by license
having max(time) = max(time) filter (where not removed);
having
子句正在检查许可证的最长时间是否为 "removed"。
这三个答案都很有道理。一般来说,distinct on
在 Postgres 中比 row_number()
更适合获取一行。如果你对子查询有严格的反感,我提供这个。