在PostgreSQL中以特定模式显示列

时间:2019-01-19 18:16:02

标签: sql postgresql case crosstab

我编写了一个查询,该查询返回一个表,该表显示公司中每个人的每月总工作时间。所以结果是:

name*****jan************feb**********march ......... dec
Tom     170:24:31    186:27:09    140:00:00........158:17:56     

我需要一个查询,给出以下输出:

name***jan***jan_salary****feb***feb_salary***....***dec***dec_salary      

每个月的工资是该月的总工作时间乘以150 $。我怎样才能做到这一点? 以下是我编写的用于计算每个人每个月的总工作时间的查询:

with hours as (
  select "Staff_Id", 
     "Date", 
     case 
       when row_number() over w % 2 = 0 then 
          TO_CHAR("Time" - lag("Time") over w,'HH24:MI:SS')
     end as hours
  from "Org"."Clock"
  window w as (partition by "Staff_Id", "Date" order by "Time")
), hours_per_month as (
  select "Staff_Id", 
     extract(year from "Date")::int as work_year,
     extract(month from "Date")::int as work_month,
     sum(hours::interval) work_hours
  from hours
  where hours is not null
  group by "Staff_Id", work_year, work_month
)
select "Staff_Id", 
   work_year,
   sum("work_hours") filter (where work_month = 1) as jan,
   sum("work_hours") filter (where work_month = 2) as feb,
   sum("work_hours") filter (where work_month = 3) as march,
   sum("work_hours") filter (where work_month = 4) as april,
   sum("work_hours") filter (where work_month = 5) as may,
   sum("work_hours") filter (where work_month = 6) as june,
   sum("work_hours") filter (where work_month = 7) as july,
   sum("work_hours") filter (where work_month = 8) as aug,
   sum("work_hours") filter (where work_month = 9) as sep,
   sum("work_hours") filter (where work_month = 10) as oct,
   sum("work_hours") filter (where work_month = 11) as nov,
   sum("work_hours") filter (where work_month = 12) as dec
from hours_per_month  
group by "Staff_Id", work_year

1 个答案:

答案 0 :(得分:1)

我认为您可以将薪水添加到“ hours_per_month”子查询中,如下所示:

select "Staff_Id", 
   extract(year from "Date")::int as work_year,
   extract(month from "Date")::int as work_month,
   sum(hours::interval) work_hours,
   trunc (extract (epoch from sum(hours::interval)) / 3600) * 150 as salary
from hours
where hours is not null
group by "Staff_Id", work_year, work_month

这假定您要全时支付(15.8小时= 15个小时的支付时间),但如果不支付,则很容易进行调整。

extract (hours也可以工作,但是如果总小时数> 24则不行。我认为,即使在这样的情况下假设不可行,也不值得假设一个人一次要工作超过24小时。另外,您以后可能会不经意间克隆此代码,使其在“机器时间”之类的条件下工作,在这种情况下,这很有可能。

然后,在您的主查询中:

select "Staff_Id", 
   work_year,
   sum("work_hours") filter (where work_month = 1) as jan,
   sum(salary) filter (where work_month = 1) as jan_salary,
   sum("work_hours") filter (where work_month = 2) as feb,
   sum(salary) filter (where work_month = 2) as feb_salary,
   ...
   sum("work_hours") filter (where work_month = 12) as dec,
   sum(salary) filter (where work_month = 12) as dec_salary
from hours_per_month  
group by "Staff_Id", work_year

完全是题外话,我并不想告诉您如何过生活,但是当我看到字段名和表名的引号时,将其解开是在查询的最后一步(呈现输出),它使我的皮肤爬行。它还引入了很多出错的机会。碰巧的是,我并不孤单:

https://wiki.postgresql.org/wiki/Don%27t_Do_This#Don.27t_use_upper_case_table_or_column_names