从数据透视表中的另一个列值过滤 varchar 列

Filter varchar col from another col value in pivot

我有一个 table 如下所示:

object_key created_by updated_on updated_by attr_type value_name value_num
1 user1 3/21/2021 user1 name John
1 user4 4/15/2021 user3 mobile_number 4567865
1 user3 4/21/2021 user2 office_number 2378783

我正在尝试使用查询进行数据透视:

SELECT object_key,
    max(created_on) AS created_on,
    max(updated_on) AS updated_on,
    max(updated_by) FILTER (WHERE updated_on = max(updated_on)) AS updated_by,
    max(array_to_string(value_name, '||'::text)) FILTER (WHERE attr_type = 'name' )as name,
    max(array_to_string(value_num, '||'::text)) FILTER (WHERE attr_type = 'mobile_number') AS mobile_number,
    max(array_to_string(value_num, '||'::text)) FILTER (WHERE attr_type = 'office_number') AS office_number
FROM object_attributes   
GROUP BY object_key;

旋转 table 必须像:

object_key created_by updated_on updated_by name mobile_number office_number
1 user1 4/21/2021 user2 John 4567865 2378783

updated_by 应该来自每个 object_key.

具有最高 updated_on 日期的行

但是 FILTER (WHERE updated_on = max(updated_on)) 在查询中不起作用。

有没有办法 select updated_by 使用枢轴中的 updated_on

一种方法是使用 window 函数 first_value:

 SELECT 
    object_key,
    max(created_on) AS created_on,
    max(updated_on) AS updated_on,
    first_value(updated_by) over(order updated_on desc) AS updated_by,
    max(array_to_string(value_name,'||')) FILTER (WHERE attr_type = 'name' )as name,
    max(array_to_string(value_num, '||')) FILTER (WHERE attr_type = 'mobile_number') AS mobile_number,
    max(array_to_string(value_num, '||')) FILTER (WHERE attr_type = 'office_number') AS office_number
FROM object_attributes   
GROUP BY object_key;

可以通过单个 SELECT 将 window 函数与 DISTINCT ON 相结合来实现:

改编为 table 最终在 your fiddle 中披露的定义:

SELECT DISTINCT ON (object_key)
       object_key
     , first_value(created_by) OVER w AS created_by
     , updated_on
     , updated_by
     , min(array_to_string(value_name, '||')) FILTER (WHERE attr_type = 'Name'         ) OVER w AS "Name"
     , min(array_to_string(value_num , '||')) FILTER (WHERE attr_type = 'Mobile_number') OVER w AS "Mobile_number"
     , min(array_to_string(value_num , '||')) FILTER (WHERE attr_type = 'Office_number') OVER w AS "Office_number"
--   , min(array_to_string(value_name, '||')) FILTER (WHERE attr_type = 'status'       ) OVER w AS status  -- ??
FROM   object_attributes
WHERE  object_key IN (1,2)
WINDOW w AS (PARTITION BY object_key ORDER BY updated_on)
ORDER  BY object_key, updated_on DESC NULLS LAST;

db<>fiddle here

这行得通,因为 DISTINCT ON window 函数之后应用。考虑 SELECT 查询中的事件序列:

  • Best way to get result count before LIMIT was applied

我们可以在聚合 window 函数中使用 FILTER 子句。参见:

  • Conditional lead/lag function PostgreSQL?

为了缩短代码,WINDOW 子句是可选的,您也可以将其拼写为 our 4x,结果相同。

为什么你可能需要 NULLS LAST:

  • Sort by column ASC, but NULL values first?

相关:

  • Get values from first and last row per group
  • Select first row in each GROUP BY group?