PostgreSQL动态列结果数

时间:2018-06-27 06:14:18

标签: sql postgresql pivot crosstab

我有这样的桌子

id   | firstname | lastname | object | total
--------------------------------------------
 1   | John      | Doe      | obj1   | 2
 2   | Mark      | Dew      | obj3   | 1
 3   | Steve     | Foey     | obj1   | 4
 4   | John      | Doe      | obj4   | 2
 5   | Mark      | Dew      | obj2   | 5
 6   | Steve     | Foey     | obj3   | 1
 --  | --        | --       | --     | --
 20  | Mark      | Dew      | obj10  | 1

并期望这样的结果:

id   | name       | obj1 | obj2 | obj3 | obj4 | .. | obj10 |
------------------------------------------------------------
 1   | John Doe   |   2  |   0  |   0  |   2  | .. |   0   |
 2   | Mark Dew   |   0  |   5  |   1  |   0  | .. |   1   |
 3   | Steve Foey |   4  |   0  |   1  |   0  | .. |   0   |

什么是我的问题的最佳解决方案(查询)?我是sql新手。请帮我。谢谢。

2 个答案:

答案 0 :(得分:0)

这是希望的新样式

SELECT FIRSTNAME ,LASTNAME  , CASE WHEN POSITION ( 'OBJ1') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ1' IN  STR )+5 ,1) :: INT END  AS OBJ1,
 CASE WHEN POSITION ( 'OBJ2') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ2' IN  STR )+5 ,1) :: INT END AS OBJ2,
 CASE WHEN POSITION ( 'OBJ3') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ3' IN  STR )+5 ,1) :: INT END AS OBJ3,
 CASE WHEN POSITION ( 'OBJ4') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ4' IN  STR )+5 ,1) :: INT END AS OBJ4,
 CASE WHEN POSITION ( 'OBJ5') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ5' IN  STR )+5 ,1) :: INT END AS OBJ5,
 CASE WHEN POSITION ( 'OBJ6') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ6' IN  STR )+5 ,1) :: INT END AS OBJ6,
 CASE WHEN POSITION ( 'OBJ7') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ7' IN  STR )+5 ,1) :: INT END AS OBJ7,
 CASE WHEN POSITION ( 'OBJ8') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ8' IN  STR )+5 ,1) :: INT END AS OBJ8,
 CASE WHEN POSITION ( 'OBJ9') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ9' IN  STR )+5 ,1) :: INT END AS OBJ9,
 CASE WHEN POSITION ( 'OBJ10') IN  STR ) = 0 THEN NULL ELSE  SUBSTR( STR ,POSITION ('OBJ10' IN  STR )+6 ,1) :: INT END AS OBJ10
 FROM 
( SELECT ID, FIRSTNAME ,LASTNAME  , STRING_AGG(OBJECT :: TEXT || '$' || TOTAL ::TEXT ,',') AS 
FROM YOURTABLE 
WHERE OBJECT 
GROUP BY ID, FIRSTNAME ,LASTNAME )A

答案 1 :(得分:0)

在postgresql中,与filter子句一起使用时,pivot非常简单。

  select
    first_name,
    last_name,
    coalesce(sum(total) filter(where object='obj1'),0) as obj1,
    coalesce(sum(total) filter(where object='obj2'),0) as obj2,
    coalesce(sum(total) filter(where object='obj3'),0) as obj3,
    coalesce(sum(total) filter(where object='obj4'),0) as obj4,
    coalesce(sum(total) filter(where object='obj5'),0) as obj5,
    coalesce(sum(total) filter(where object='obj6'),0) as obj6,
    coalesce(sum(total) filter(where object='obj7'),0) as obj7,
    coalesce(sum(total) filter(where object='obj8'),0) as obj8,
    coalesce(sum(total) filter(where object='obj9'),0) as obj9,
    coalesce(sum(total) filter(where object='obj10'),0) as obj10
  from table1
  group by first_name,last_name