将 header 行转换为列 PostgreSQL

Converting the header row to a column PostgreSQL

我是 PostgreSQL 新手。我有一个 table 包含下面提到的三列,我想将 header 行转换为在另一列中具有相应值的列,最后是一个新列,用于检查该值是否丢失.

ID   NAME   EMAIL            SALARY
1    John   ''               1000
2    Sam    feeeee@asd.com   6000
3    Tom    aeesde@asd.com   9000
4    Bob    mnnke@asd.com    500
5    Lari   kllewl@asd.com   3000

每个 ID 的预期输出:

ID   fields      Value            Verified
 1    NAME        John              Yes
      EMAIL        ''               No
      SALARY      1000              Yes

 2    NAME        Sam               Yes
      EMAIL      feeeee@asd.com     Yes
      SALARY      6000              Yes

您所谓的 header 行根本就不是行,而只是列名。每个 ID 和列需要一行。虽然这是我宁愿在应用程序中而不是在 SQL 中执行的操作,但它当然是可能的。每列需要一个查询。将他们的结果与 UNION ALL.

粘合在一起
select
  id, 
  'NAME' as fields,
  name as value,
  case when name is null or name = '' then 'No' else 'Yes' as verified
from mytable
union all
select
  id, 
  'EMAIL' as fields,
  email as value,
  case when email is null or email = '' then 'No' else 'Yes' as verified
from mytable
union all
select
  id, 
  'SALARY' as fields,
  cast(salary as varchar) as value,
  case when salary is null then 'No' else 'Yes' as verified
from mytable
order by id, fields;

但如前所述,最好只 select * from mytable 并关心应用中数据的呈现方式。这可能也快得多。

另一种选择是使用带有 VALUES 子句的 CROSS JOIN,将列转换为行:

select t.id, 
       u.*,
       case 
         when u.value = '' or u.value is null then 'No'
         else 'Yes'
       end as verified
from the_table t
  cross join lateral (
     values ('NAME', name), ('EMAIL', email), ('SALARY', salary::text)
  ) as u(column_name, value)
order by t.id, u.column_name  

这写起来更短,也更容易维护,但我发现 Thorsten Kettner 的 UNION ALL 方法在某些情况下更快。