【问题标题】:Show salary history in a table format from a listing format?从列表格式以表格格式显示工资历史记录?
【发布时间】:2012-09-29 05:20:14
【问题描述】:

我确信这对于 SQL 的铁杆极客来说不是一个难题,但我需要一些帮助。这适用于 SQL Server 2000(继承的项目!)。

我有一张如下所示的工资表:

EmployeeID  |  EffectiveDate  | Salary
1           |   2/1/2011      | 500
1           |   6/1/2011      | 600
1           |   12/1/2011     | 650

我需要创建一个查询,该查询将按月输出给定年份的这些薪水。所以输出会是这样的

EmployeeID  | Jan | Feb | Mar | Apr | Apr | May | Jun | Jul | Aug | Sept | Oct | Nov | Dec
1           | 500 | 500 | 500 | 500 | 500 | 500 | 600 | 600 | 600 | 600  | 600 | 600 | 650

我知道必须有一种方法可以使用 SQL 有效地做到这一点,但我似乎无法做到这一点。显然,我会用 SQL 命名上面的月份列,例如 SELECT EmployeeID, 'Jan' AS Jan, 'Feb' AS Feb, 等等,但语句的其余部分更难,因为我正在寻找范围。

【问题讨论】:

  • 你确定你需要在 SQL 中完成所有工作(删除 C# 标记比)还是你可以在 C# 中显示部分(不确定问题是什么,因为它很简单WHERE EffectiveDate>@StartYear and EffectiveDate<@EndYear)跨度>
  • 这会给我多个结果,因为工资会在一年内发生变化。

标签: c# tsql sql-server-2000 pivot


【解决方案1】:

由于您使用的是 SQL Server 2000,它没有 PIVOT 函数,因此您必须使用聚合函数和 CASE 语句来复制它。类似这样:

select  employeeid,
  sum(case when DatePart(Month, EffectiveDate) = 1 then Salary end) as Jan,
  sum(case when DatePart(Month, EffectiveDate) = 2 then Salary end) as Feb,
  sum(case when DatePart(Month, EffectiveDate) = 3 then Salary end) as Mar,
  sum(case when DatePart(Month, EffectiveDate) = 4 then Salary end) as Apr,
  sum(case when DatePart(Month, EffectiveDate) = 5 then Salary end) as May,
  sum(case when DatePart(Month, EffectiveDate) = 6 then Salary end) as Jun,
  sum(case when DatePart(Month, EffectiveDate) = 7 then Salary end) as Jul,
  sum(case when DatePart(Month, EffectiveDate) = 8 then Salary end) as Aug,
  sum(case when DatePart(Month, EffectiveDate) = 9 then Salary end) as Sep,
  sum(case when DatePart(Month, EffectiveDate) = 10 then Salary end) as Oct,
  sum(case when DatePart(Month, EffectiveDate) = 11 then Salary end) as Nov,
  sum(case when DatePart(Month, EffectiveDate) = 12 then Salary end) as Dec
from  yourtable
group by employeeid

SQL Fiddle with Demo

编辑,根据您上面的 cmets 将值从一个月转移到下一个月,这里有一个可能适合您的解决方案。

declare @query as nvarchar(max) = '',
  @rowcount as int = 1,
  @pivotrow as int,
  @currentMonthSalary as int = 0,
  @priorMonthSalary as int = 0,
  @employeeid int 

select distinct effectivedate
into #colspivot
from yourtable

while @rowcount <= 12 -- loop thru each month
  begin

    set @pivotrow = (select top 1 datepart(month, effectivedate)
                        from #colspivot
                        order by datepart(month, effectivedate))

    select @currentMonthSalary = salary, @employeeid = EmployeeID
            from yourtable
            where datepart(month, effectivedate) = @pivotrow

    if @pivotrow = @rowcount
        begin
            insert into FinalData (employeeid, effectivemonth, salary)
            select @employeeid, cast(DateName(month, DateAdd(month, @pivotrow, 0) -1) as varchar(3)), @currentMonthSalary

            set @query = @query + ', sum(case when effectivemonth = ''' +  cast(DateName(month, DateAdd(month, @pivotrow, 0) -1) as varchar(3)) + ''' 
                                        then ' + cast(@currentMonthSalary as varchar(10)) + ' end) as '+ cast(DateName(month, DateAdd(month, @pivotrow, 0) -1) as varchar(3))

            delete from #colsPivot where datepart(month, effectivedate) = @pivotRow

            set @priorMonthSalary = @currentMonthSalary
        end
    else
        begin
            insert into FinalData (employeeid, effectivemonth, salary)
            select @employeeid, cast(DateName(month, DateAdd(month, @rowcount, 0) -1) as varchar(3)), @priorMonthSalary

            set @query = @query + ', sum(case when effectivemonth = ''' + cast(DateName(month, DateAdd(month, @rowcount, 0) -1) as varchar(3)) + '''  
                        then ' +  cast(@priorMonthSalary as varchar(10)) + ' end) as '+cast(DateName(month, DateAdd(month, @rowcount, 0) -1) as varchar(3))
        end

    if @rowcount <= 12
      set @rowcount = @rowcount + 1
  end

set @query = 'select employeeid '+ @query 
              + ' from FinalData group by employeeid;'

exec(@query) 

SQL Fiddle with Demo。在循环创建 sql 语句时,我创建了一个新表 FinalData 来存储每个月的数据。

【讨论】:

  • 好的,有道理。但是,如果在我的第一条消息中不清楚,那么只有表条目有变化。因此,如果 2 月和 5 月发生变化,则 3 月和 4 月的表格结果应该与 2 月相同。您的答案不会说明这一点,对吧?
  • 我猜这与 Jim Beam 想要的略有不同 - 我的理解是他将函数定义为 3 个值,但希望随时都有结果Salary(month) = {select Salary where EffectiveDate.NoDay &lt;= TheMonthDate.NoDay }
  • @alexei true,让我看看如何继续
  • @JimBeam 请看我的编辑,我创建了一个动态版本,应该在 SQL Server 2000 中工作以产生您需要的结果。
  • 感谢您的编辑 - 以上应该可以工作。我还实现了类似于 Alexei 建议的东西。由于缺少 PIVOT 函数,使用子查询也可能同样有效。
【解决方案2】:

试试这个查询:

Select  EmployeeID, [Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug],[Sep],[Oct],[Nov],[Dec]
From
(
    Select EmployeeID, CAST(DateName(MONTH,EffectiveDate) as varchar(3)) as Mon, Salary
        From Employees

) as SourceTable

PIVOT
(
    Sum(Salary)
    For Mon in ( [Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug],[Sep],[Oct],[Nov],[Dec] )
) as PivotTable

它产生的结果与您在输出样本中显示的结果完全相同。

【讨论】:

  • 抱歉,我正在使用的 SQL Server 2000 不支持 Pivot(无论好坏!)
  • @JimBeam:我的错!我没有看到 SQL Server 2000 的标签 :(
猜你喜欢
  • 2012-04-27
  • 1970-01-01
  • 2014-06-30
  • 2021-05-02
  • 2018-12-10
  • 2012-11-15
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
相关资源
最近更新 更多