2016-06-09 59 views
0

我需要将行数据转换为特定条件下的列。假设我们在2015年,那么它需要将下一年的数据作为新的列。请看看表A,可以有人建议我如何达到预期的结果?SQL Server中的行(可能为Pivot)

表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在以下情况下

+0

你尝试过这么远吗?我们很乐意提供帮助,但您也必须自己投入一些努力。 –

+0

最近我已经转移到SQL编码。我已经通过了枢轴的几个门户。看起来Pivot可以将行转换为列,但是,我还没有任何线索如何实现我的场景。 –

+0

这是绝对可行的,但在SQL Server中执行起来相当复杂,而且通常最终不得不做一些动态SQL。我最近也做了同样的事情,所以我可以提供帮助,但是如果你不熟悉SQL,可能会遇到一些你会遇到的问题。如果你不明白,请询问。 –

回答

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

好吧,下面是我写的一个查询的例子,它可以做某些事情与你想要的相似。它需要一组数据并根据开始年份动态调整。我只给了你第一个支点(用于价格)。如果要在第二列以及之后进行循环,则需要创建第二个动态选择字符串,然后再加入动态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; 
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