2013-02-06 94 views
0

假設我們有以下數據集:樞軸在一個表上

Name City   Date 
Paul Milan   04/01/2013 
Charls Rome   04/01/2013 
Jim  Tokyo   04/01/2013 
Justin San Francisco 04/01/2013 
Bill London   04/01/2013 
Paul Berlin   05/01/2013 
Charls El Cairo  05/01/2013 
Jim  Milan   05/01/2013 
Justin Paris   05/01/2013 
Bill Madrid   05/01/2013 

每個人[Name][Date]某月某日訪問了某鎮[City]

我們想要做的是有一個表,[Name][City day 1][City day 2]如下:

Name City 04/01/2013 City 05/01/2013 
Paul Milan   Berlin 
Charls Rome   El Cairo 
Jim  Tokyo   Milan 
Justin San Francisco Paris 
Bill London   Madrid 

我們怎麼能寫這樣做的查詢?

回答

2

這種類型的數據轉換被稱爲PIVOT。從SQL Server 2005開始,有一個函數可以爲你執行這個數據輪換。但是這可以通過許多不同的方式來完成。

您可以使用聚合函數和CASE數據:

select 
    name, 
    max(case when date = '2013-04-01' then city end) [City 04/01/2013], 
    max(case when date = '2013-05-01' then city end) [City 05/01/2013] 
from yourtable 
group by name 

SQL Fiddle with Demo

或者你可以使用PIVOT功能:

select name, [2013-04-01] as [City 04/01/2013], [2013-05-01] as [City 05/01/2013] 
from 
(
    select name, city, date 
    from yourtable 
) src 
pivot 
(
    max(city) 
    for date in ([2013-04-01], [2013-05-01]) 
) piv 

SQL Fiddle with Demo

這甚至可以多次參加你的桌子上完成:

select d1.name, 
    d1.city [City 04/01/2013], 
    d2.city [City 05/01/2013] 
from yourtable d1 
left join yourtable d2 
    on d1.name = d2.name 
    and d2.date = '2013-05-01' 
where d1.date = '2013-04-01' 

SQL Fiddle with Demo

如果您知道要將日期轉換爲列的上述查詢將很有用。但是,如果你有一個未知的列數,那麼你將要使用動態SQL:

DECLARE @cols AS NVARCHAR(MAX), 
    @colNames AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(convert(char(10), date, 120)) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

select @colNames = STUFF((SELECT distinct ',' + QUOTENAME(convert(char(10), date, 120)) +' as '+ QUOTENAME('City '+convert(char(10), date, 120)) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT name, ' + @colNames + ' from 
      (
       select name, 
        city, 
        convert(char(10), date, 120) date 
       from yourtable 
      ) x 
      pivot 
      (
       max(city) 
       for date in (' + @cols + ') 
      ) p ' 

execute(@query) 

SQL Fiddle with Demo

他們都給出結果:

| NAME | CITY 04/01/2013 | CITY 05/01/2013 | 
---------------------------------------------- 
| Paul |   Milan |   Berlin | 
| Charls |   Rome |  El Cairo | 
| Jim |   Tokyo |   Milan | 
| Justin | San Francisco |   Paris | 
| Bill |   London |   Madrid | 
1

的simpliest可能的方式是通過使用CASE

SELECT Name, 
     MAX(CASE WHEN DATE = '04/01/2013' THEN City END) [City 04/01/2013], 
     MAX(CASE WHEN DATE = '05/01/2013' THEN City END) [City 05/01/2013] 
FROM tableName 
GROUP BY Name