行到SQL Server中的列(可能是Pivot)

时间:2016-06-09 19:01:48

标签: sql-server pivot-table ssis-2012

我需要将Rows数据转换为特定条件下的列。假设我们在2015年那么它需要将下一年的数据作为新列获取。请看一下表A,有人建议我如何达到预期的结果?

表A:

EmpID   Year     Price     Cm       St1    St2 
03      2015      1        AB       1          0
03      2016      2        CD       0          1
04      2016      2        XY       0          1
04      2015      20       ZX       0          1 

预期产出:

EmpID  Year Y1_Price Y1_Cm  Y1_St1  Y1_St2 Y2_Price Y2_Cm  Y2_St1  Y2_St2
03     2015  1       AB     1       0      2        CD     0       1
03     2016  2       CD     0       1      NULL     NULL   NULL    NULL 
04     2016  2       XY     0       1      NULL     NULL   NULL    NULL
04     2015  20      ZX     0       1      2        XY     0       1

请帮我编写以下场景的SQL

3 个答案:

答案 0 :(得分:3)

请把事情复杂化。我花了大约10分钟来编写这个查询,这很容易实现。

@Sandeep - 使用下面的脚本,它将为您提供您正在寻找的内容。假设Test是你的表名。

查询:

WITH CTE AS
(
SELECT EmpId, Year, Price, Cm, St1, St2, ROW_NUMBER() OVER(PARTITION BY EmpId ORDER BY Year) RNo
FROM TEST
)
SELECT T1.EmpId, T1.Year
    , T1.Price Y1_Price, T1.Cm Y1_Cm, T1.St1 Y1_St1, T1.St2 Y1_St2
    , T2.Price Y2_Price, T2.Cm Y2_Cm, T2.St1 Y2_St1, T2.St2 Y2_St2
FROM CTE T1
LEFT JOIN CTE T2 ON T1.EmpId = T2.EmpId AND T1.RNo + 1 = T2.RNo

答案 1 :(得分:2)

假设您正在进行年度比较

Declare @Table table (EmpID varchar(25),Year int,Price money,CM varchar(25), St1 int,St2 int)
Insert into @Table (EmpID,Year,Price,Cm,St1,St2) values
('03',2015,1,'AB',1,0),
('03',2016,2,'CD', 0,1),
('04',2016,2,'XY',0,1),
('04',2015,20,'ZX',0,1)

Select A.EmpID
      ,A.Year
      ,Y1_Price = A.Price
      ,Y1_CM    = A.CM
      ,Y1_St1   = A.ST1
      ,Y1_St2   = A.ST2
      ,Y2_Price = B.Price
      ,Y2_CM    = B.CM
      ,Y2_St1   = B.ST1
      ,Y2_St2   = B.ST2
 From @Table A
 Left Join @Table B on (A.EmpID = B.EmpID and A.Year+1=B.Year)

返回

EmpID   Year    Y1_Price    Y1_CM   Y1_St1  Y1_St2  Y2_Price    Y2_CM   Y2_St1  Y2_St2
03      2015    1.00        AB      1       0       2.00        CD      0       1
03      2016    2.00        CD      0       1       NULL        NULL    NULL    NULL
04      2016    2.00        XY      0       1       NULL        NULL    NULL    NULL
04      2015    20.00       ZX      0       1       2.00        XY      0       1

答案 2 :(得分:1)

好的,下面是我编写的一个查询示例,它可以执行类似于您想要的操作。它需要一组数据并根据起始年份动态调整。我只给你第一个支点(价格)。如果要在第二列及以后的列上进行透视,则需要创建第二个动态选择字符串,然后再在动态SQL中的新数据透视表上进行连接。

declare @startYear int = 2010;
declare @startDate datetime = '1/1/2010 00:00:00.000';
declare @endYear int = year(getutcdate());
declare @endDate datetime = convert(datetime, '12/31/' + convert(nvarchar, @endYear) + ' 23:59:59.997');

-- our variables for string concatenation
declare     @yearString             nvarchar(max)   = ''
            , @piv1YearSelectionString  nvarchar(max)   = ''
            , @query                    nvarchar(max)   = ''
;

-- check for the existence of our temp table and dropping it
if exists (
    select  * from tempdb.dbo.sysobjects o
    where o.xtype in ('U') 
    and o.id = object_id(N'tempdb..#rawData')
)
begin
    drop table #rawData;
end

-- create our temp table
create table  #rawData
(
    EmployeeId          nvarchar(50)
    , InvoiceYear       int
    , Price             money
    , Cm                nvarchar(50)
    , St1               int
    , St2               int
);

-- concatenate our strings with our year column names
while (@startYear <= @endYear)
begin
    -- creates a string of values like [2010, 2011, ...]
    set @yearString                     = @yearString + '[' + convert(nvarchar, @startYear) + ']';
    -- creates a string of values like ['COALESCE(MAX[a].[2011], 0) as [Price2011], ...
    set @piv1YearSelectionString        = @piv1YearSelectionString + 'COALESCE(MAX([a].[' + convert(nvarchar, @startYear) + ']), 0) AS [Price' + convert(nvarchar, @startYear) + ']';

    set @startYear                      = @startYear + 1;

    -- adds commas to the strings
    if @startYear <= @endYear
    begin
        set @yearString                 = @yearString + ', ';
        set @piv1YearSelectionString    = @piv1YearSelectionString + ', ';
    end
end
;

-- build the query here
set @query = '
declare @sDate datetime = ''' + convert(varchar, @startDate) + ''';
declare @eDate datetime = dateadd(s, -1, dateadd(yyyy, 1, @sDate));
declare @stopDate datetime = ''' + convert(varchar, @endDate) + ''';

while @sDate < @stopDate
begin

    -- uncomment the line below to see the dates
    --select @sDate, @eDate;

    -- collect your input table
    insert #rawData ( employeeId, invoiceYear, Price, Cm, St1, St2 )
    select
        EmployeID
        , year(InvoiceDate) as InvoiceYear
        , Price
        , Cm
        , St1
        , St2

    from
        <SourceQuery>
    where
        InvoiceDate between @sdate and @eDate
    ;

    set @sDate = dateadd(yyyy, 1, @sDate);
    set @eDate = dateadd(ms, -1, dateadd(yyyy, 1, @sDate));
end
 -- dynamically pivot
select 
    a.EmployeeId
    , ' + @piv1YearSelectionString + '
from
(
    select
        piv1.CompanyId, piv1.CompanyName, ' + @yearString + '
    from
        #rawData
    pivot
    (
        max(Price)
        for [invoiceYear] in (' + @yearString + ')
    ) as piv1
) a

group by
    a.EmployeeId

order by
    a.EmployeeId
';

-- run the query
execute(@query);

-- clean up
drop table #rawdata;