PostgreSQL 9.3:交叉表查询中的计数无效

时间:2015-03-24 04:54:13

标签: postgresql postgresql-9.3 crosstab

我有以下数据显示在数据透视表中:

以下表Employee包含员工详细信息:

          Employee_Number              Employee_Role                Group_Name
          --------------------------------------------------------------------
           EMP101                      C# Developer                  Group_1               
           EMP102                      ASP Developer                 Group_1               
           EMP103                      SQL Developer                 Group_2               
           EMP104                      PLSQL Developer               Group_2               
           EMP101                      Java Developer                                           
           EMP102                      Web Developer                                            
           EMP101                      DBA                                             
           EMP105                      DBA                                             
           EMP106                      SQL Developer                 Group_3               
           EMP107                      Oracle Developer              Group_3               
           EMP101                      Oracle Developer              Group_3               
           EMP108                      JSP                           Group_4               
           EMP108                      JS                            Group_5               
           EMP101                      C# Developer                  Group_1               
           EMP101                      C# Developer                  Group_1               
           EMP101                      C# Developer                  Group_1               
           EMP101                      C# Developer                  Group_1               

我想将输出显示到数据透视表中,如下所示:

Employee_Number     TotalRoles      TotalGroups       Available     Others     Group_1     Group_2      Group_3      Group_4      Group_5
------------------------------------------------------------------------------------------------------------------------------------------
   EMP101               8                5                2           6           5           0            1             0           0
   EMP102               2                5                1           1           1           0            0             0           0
   EMP103               1                5                1           0           0           1            0             0           0   
   EMP104               1                5                1           0           0           1            0             0           0
   .......
   .......

我正在使用此脚本:

SELECT * FROM crosstab(
      $$SELECT grp.*, e.group_name
     , CASE WHEN e.employee_number IS NULL THEN 0 ELSE 1 END AS val
    FROM  (
       SELECT employee_number
    , count(employee_role)::int            AS total_roles
    , (SELECT count(DISTINCT group_name)::int
       FROM   employee
       WHERE  group_name <> '')            AS total_groups
    , count(group_name <> '' OR NULL)::INT AS available                    
    , count(group_name =  '' OR NULL)::int AS others
       FROM   employee
       GROUP  BY employee_number
       ) grp
    LEFT   JOIN employee e ON e.employee_number = grp.employee_number
          AND e.group_name <> ''         
    ORDER  BY grp.employee_number, e.group_name$$
     ,$$VALUES ('Group_1'),('Group_2'),('Group_3'),('Group_4'),('Group_5')$$
   ) AS ct (employee_number text
      , total_roles  int
      , total_groups int
      , available    int
      , others       int
      , Group_1    int
      , Group_2    int
      , Group_3    int
      , Group_4    int
      , Group_5    int);    

但是在Available的输出中输入错误的EMP101它必须为2,因为他是 可在group_1group_3中找到。但是错误的可用。

1 个答案:

答案 0 :(得分:1)

我看到两个问题: 1)count(group_name <> '' OR NULL)将计算每次出现的group_name不是空白的,即当有重复时,您将重复计算值。 2)您没有对组计数进行分组 - 交叉表功能不会为您聚合,因此当员工不止一次属于某个组时,您将获得不正确的组计数。以下查询具有不同的计算可用方式,并对计数进行分组。你会得到缺失值的空值,但你之前得到了它们: - )

SELECT * FROM crosstab(
      $$SELECT grp.*, e.group_name
     ,  val
    FROM  (
       SELECT employee_number
    , count(employee_role)::int            AS total_roles
    , (SELECT count(DISTINCT group_name)::int
       FROM   employee
       WHERE  group_name <> '')            AS total_groups

    , (count(distinct group_name) - count(distinct group_name =  '' OR NULL))::int AS available   

    , count(group_name =  '' OR NULL)::int AS others
       FROM   employee
       GROUP  BY employee_number
       ) grp
    LEFT   JOIN 
    (select employee_number,group_name,count(*) as val from employee group by employee_number,group_name) e
      ON e.employee_number = grp.employee_number

    ORDER  BY grp.employee_number, e.group_name$$
     ,$$VALUES ('Group_1'),('Group_2'),('Group_3'),('Group_4'),('Group_5')$$
   ) AS ct (employee_number text
      , total_roles  int
      , total_groups int
      , available    int
      , others       int
      , Group_1    int
      , Group_2    int
      , Group_3    int
      , Group_4    int
      , Group_5    int);