POSTGRESQL-Converting multiple rows with different values to columns 到一行和不同的列

POSTGRESQL-Converting multiple rows with different values to columns to one row and different columns

您好,作为 POSTGRESQL 的新手,我需要将多行数据转换为一行多列。如何在 POSTGRESQL 中执行此操作。 我要转换以下数据

这是一种蛮力方法。如果你有很多流派,它可能会变得乏味。

首先创建table并插入数据。为了说明目的,我制作了另一部电影:

CREATE TABLE t1 (movie text, genre text);

INSERT INTO t1 (movie, genre)
     VALUES ('ABC', 'Action'),
            ('ABC', 'Fantasy'),
            ('DEF', 'Comedy'),
            ('DEF', 'Action');

要获得所需的列,首先您可以为每部电影每种类型创建一行:

SELECT movie,
  CASE WHEN genre = 'Action' THEN 1 ELSE 0 END AS isAction,
  CASE WHEN genre = 'Fantasy' THEN 1 ELSE 0 END AS isFantasy,  
  CASE WHEN genre = 'Comedy' THEN 1 ELSE 0 END AS isComedy,  
  CASE WHEN genre = 'Crime' THEN 1 ELSE 0 END AS isCrime
 FROM t1

行数过多

movie isaction isfantasy iscomedy iscrime
ABC 1 0 0 0
ABC 0 1 0 0
DEF 0 0 1 0
DEF 1 0 0 0

但是我们可以通过求和和 GROUP BY 流派来减少行数

WITH t2 as (
SELECT movie,
  CASE WHEN genre = 'Action' THEN 1 ELSE 0 END AS isAction,
  CASE WHEN genre = 'Fantasy' THEN 1 ELSE 0 END AS isFantasy,  
  CASE WHEN genre = 'Comedy' THEN 1 ELSE 0 END AS isComedy,  
  CASE WHEN genre = 'Crime' THEN 1 ELSE 0 END AS isCrime
 FROM t1)
 
 SELECT movie, sum(isAction) as isAction,
               sum(isFantasy) as isFantasy, 
               sum(isComedy) as isComedy, 
               sum(isCrime) as isCrime
  FROM t2
  GROUP BY movie

这给出了

movie isaction isfantasy iscomedy iscrime
ABC 1 1 0 0
DEF 1 0 1 0

现在讨论一些数据类型并将这些数据放入 table。如所写,这些查询将具有 isAction 等列作为 bigint。您可能实际上想要布尔值,在这种情况下,您必须先转换为 int,然后再转换为布尔值(例如 sum(isAction)::int::bool as isAction...)。

要将数据放入 table 中,请将最后一个 SELECT 查询替换为 SELECT INTO 查询,这会自动为您创建一个新的 table。

可以使用bool_or()聚合函数来实现:

select movie, 
       bool_or(genre = 'Action') as  is_action,
       bool_or(genre = 'Fantasy') as  is_fantasy,
       bool_or(genre = 'Crime') as  is_crime,
       bool_or(genre = 'Comedy') as  is_comedy
from the_table       
group by movie       

请注意,这个 returns 是一个真正的 boolean 值,而不是 01,我发现对于这样的“标志”列,后者更合乎逻辑。如果对于 true/false 标志,您确实更喜欢整数而不是布尔值,只需将函数的结果转换为 int,例如bool_or(....)::int