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]访问过某个城镇的地方。[City][Date]

我们想要做的是有一个带有[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

我们如何为此编写查询?

4

2 回答 2

2

这种类型的数据转换称为PIVOT. 从 SQL Server 2005 开始,有一个函数可以为您执行此数据轮换。但这可以通过许多不同的方式来完成。

您可以使用聚合函数和 aCASE透视数据:

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

或者您可以使用以下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

他们都给出了结果:

|   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 |
于 2013-02-06T15:44:26.057 回答
1

最简单的方法是使用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
于 2013-02-06T15:44:54.000 回答