sql - 使用 ARRAY_AGG 获取列中的第一个非 NULL 值是否浪费?

标签 sql postgresql greatest-n-per-group postgresql-performance array-agg

我使用 PostgreSQL 14 来管理一个存储医生表更新的表:用户可以更新医生的名字、姓氏和/或年龄。更新操作未触及的字段具有 NULL值。

这是涉及两名不同医务人员的四次编辑的示例。 ID 为 3 的医生收到了三个更新:前两个正在更新 age字段中,第三个触及 first_name :

SELECT * FROM medic_edits;
<表类=“s-表”> <标题> id medic_id 名字 姓氏 年龄 <正文> 1 1 印地 2 3 59 3 3 63 4 3 鲍勃

我想合并此表,以便在结果表中每个医生有一行,提供累积编辑。这是我当前的查询及其产生的输出:

SELECT
  medic_id,
  (ARRAY_REMOVE(ARRAY_AGG(first_name ORDER BY id DESC), NULL))[1] AS first_name,
  (ARRAY_REMOVE(ARRAY_AGG(last_name ORDER BY id DESC), NULL))[1] AS last_name,
  (ARRAY_REMOVE(ARRAY_AGG(age ORDER BY id DESC), NULL))[1] AS last_name
FROM medic_edits
GROUP BY medic_id
;
<表类=“s-表”> <标题> medic_id 名字 姓氏 姓氏 <正文> 1 印地 3 鲍勃 63

这正是我期望的输出,但我怀疑 ARRAY_REMOVE/ARRAY_AGG逻辑有点浪费。我想知道这里是否有一种方法可以利用分区来获得良好的利润,FIRST_VALUE函数看起来非常相关。

最佳答案

是的,这是浪费。我希望这会更快:

SELECT DISTINCT ON (medic_id)
       medic_id
     , first_value(first_name) OVER (PARTITION BY medic_id ORDER BY CASE WHEN first_name IS NOT NULL THEN id END) AS first_name
     , first_value(last_name)  OVER (PARTITION BY medic_id ORDER BY CASE WHEN last_name  IS NOT NULL THEN id END) AS last_name
     , first_value(age)        OVER (PARTITION BY medic_id ORDER BY CASE WHEN age        IS NOT NULL THEN id END) AS age
FROM   medic_edits;

对于降序的 id 值,请改用:

       first_value(first_name) OVER (PARTITION BY medic_id ORDER BY CASE WHEN first_name IS NOT NULL THEN id END DESC NULLS LAST) AS first_name

参见:

但可能还有更快的方法。还取决于确切的表定义、基数和数据分布。

参见:

关于DISTINCT ON:

在单个 SELECT 中工作,因为 DISTINCTDISTINCT ON 是在窗口函数之后应用的。请参阅:

旁白:“年龄”将会迅速腐烂。它通常更适合存储生日。

关于sql - 使用 ARRAY_AGG 获取列中的第一个非 NULL 值是否浪费?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73755206/

相关文章:

sql - 如何截断列以创建索引?

python - Postgres : unterminated quoted string at or near using psycopg2

mysql - 如何在MySQL中选择字段具有最小值的数据?

mysql - 选择最新的行以及恰好 2 行具有一个条件的行和 2 行具有不同条件的行

mysql 分组依据和最大值

sql - 如何从头开始重用sql中的游标

sql - 使用 Spark DataFrame 获取一组后所有组的 TopN

sql - 忽略 Postgresql 批量插入错误

postgresql - : SQL state: 42703 Context: Error occurred on dblink connection named "unnamed": could not execute query是什么意思

sql - 在postgresql中查找每天每小时每行的列数据总和