2016-06-09 83 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