【问题标题】:Pivot Row on PostgreSQLPostgreSQL 上的数据透视行
【发布时间】:2017-01-05 20:40:31
【问题描述】:

我有一个返回整行的查询,我需要将此结果转置到一个新表中。

SELECT id_no, stud_name, group_no, class_1, class_2, class_3, class_4 FROM tbl_stud_class

这将返回以下内容:

| id_no | stud_name | group_no | class_1 | class_2 | class_3 | class 4 |
| 1     | John Doe  | A11      | 84      | 60      | 80      | 79      |

我需要能够将此行返回为:

| id_no | stud_name | group_no | class   | grade |
| 1     | John Doe  | A11      | class_1 | 84    |
| 1     | John Doe  | A11      | class_2 | 60    |
| 1     | John Doe  | A11      | class_3 | 80    |
| 1     | John Doe  | A11      | class_4 | 79    |

有人可以指点我这样做的方法吗? 我对 PostgreSQL 很陌生,所以我不知道从哪里以及如何开始。

谢谢!

【问题讨论】:

    标签: postgresql pivot pivot-table


    【解决方案1】:

    你也可以在 postgresql 9.3+ 中使用LATERAL

    SELECT id_no, stud_name, group_no, class, grade
    FROM   tbl_stud_class 
           CROSS JOIN LATERAL ( VALUES
                         ('class_1', class_1),
                         ('class_2', class_2),
                         ('class_3', class_3),
                         ('class_4', class_4)
                ) l(class, grade)
    

    【讨论】:

      【解决方案2】:

      需要这个:

      WITH tbl_stud_class
           (id_no, stud_name, group_no, class_1, class_2, class_3, class_4) AS
      (
          VALUES
            (1, 'John Doe', 'All', 84, 60, 80, 79),
            (2, 'Aberel Dalton', 'Some', 75, 32, NULL, 80)
      )
      
      SELECT
          id_no, stud_name, group_no, 'class_1' AS class, class_1 AS grade
      FROM
          tbl_stud_class
      WHERE 
          class_1 IS NOT NULL
      UNION
      SELECT
          id_no, stud_name, group_no, 'class_2' AS class, class_2 AS grade 
      FROM
          tbl_stud_class
      WHERE 
          class_2 IS NOT NULL
      UNION
      SELECT
          id_no, stud_name, group_no, 'class_3' AS class, class_3 AS grade
      FROM
          tbl_stud_class
      WHERE 
          class_3 IS NOT NULL
      UNION
      SELECT
          id_no, stud_name, group_no, 'class_4' AS class, class_4 AS grade
      FROM
          tbl_stud_class 
      WHERE 
          class_4 IS NOT NULL 
      ORDER BY
          id_no, class ;
      

      AFAIK,没有办法以自动方式执行此操作。 PostgreSQL 有 crosstab 函数,它执行 PIVOT,但它以相反的方式工作(从您想要的输出到您的输入)。


      你有一个更短的选择,使用arraysunnest

      WITH tbl_stud_class
           (id_no, stud_name, group_no, class_1, class_2, class_3, class_4) AS
      (
          VALUES
            (1, 'John Doe', 'All', 84, 60, 80, 79),
            (2, 'Aberel Dalton', 'Some', 75, 32, NULL, 80)
      )
      
      SELECT
          *
      FROM
      (
          SELECT
              id_no, stud_name, group_no, 
              unnest(ARRAY['class_1', 'class_2', 'class_3', 'class_4']) AS class,
              unnest(ARRAY[ class_1,   class_2,   class_3,   class_4 ]) AS grade
          FROM
              tbl_stud_class
      ) AS s0        
      WHERE
          grade is not null 
      ORDER BY
          id_no, class ;
      

      【讨论】:

      • 效果也很好!非常感谢!
      猜你喜欢
      • 2021-12-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多