2013-12-17 50 views
1

我有一个表上简单的选择给出了让像下面SQL服务器 - 转换列行

enter image description here

我想写一个查询语句来输出像下面

enter image description here

有人可以帮我...

+3

听起来像你想要的枢纽。 –

+1

搜索数据透视表和sql。 – Mihai

+0

你打算如何显示数据?像这样旋转在报表和应用中比在SQL中更容易实现。 –

回答

8

因为你基本上是旋转你当前的列SaleIncomeProfit转换为行,然后将month值移动到列中,那么您将首先取消转移当前列,然后转动月份。

根据您的SQL Server版本,有几种方法可以取消数据传输。您可以使用UNPIVOT功能或CROSS APPLY:

select month, type, value 
from yourtable 
cross apply 
(
    select 'Sale', sale union all 
    select 'Income', Income union all 
    select 'Profit', Profit 
) c (type, value) 

SQL Fiddle with Demo。这会将您当前的数据转换为:

| MONTH | TYPE | VALUE | 
|-------|--------|-------| 
| Jan | Sale | 100 | 
| Jan | Income | 50 | 
| Jan | Profit | 10 | 
| Feb | Sale | 20 | 
| Feb | Income | 40 | 

然后,您可以使用PIVOT功能将月份转换为列标题。

select type, Jan, Feb, Mar, Apr 
from 
(
    select month, type, value 
    from yourtable 
    cross apply 
    (
    select 'Sale', sale union all 
    select 'Income', Income union all 
    select 'Profit', Profit 
) c (type, value) 
) d 
pivot 
(
    sum(value) 
    for month in (Jan, Feb, Mar, Apr) 
) piv; 

请参阅SQL Fiddle with Demo

,如果你有一个未知的数个月,那么你可以使用动态SQL:

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

select @cols = STUFF((SELECT distinct N',' + QUOTENAME(Month) 
        from yourtable 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = N'SELECT type, ' + @cols + N' 
      from 
      (
       select month, type, value 
       from yourtable 
       cross apply 
       (
        select ''Sale'', sale union all 
        select ''Income'', Income union all 
        select ''Profit'', Profit 
       ) c (type, value) 
      ) x 
      pivot 
      (
       sum(value) 
       for month in (' + @cols + N') 
      ) p ' 

execute sp_executesql @query; 

SQL Fiddle with Demo

+0

解决方案看起来不错。谢谢bluefeet。但是在编写查询时,它的动态并不知道月份列表。它也可能会延续到十二月。所以今天当我运行到四月时,明天可能要到六月。任何想法如何解决? –

+0

@KrishnarajBarvathaya看到我的编辑,你将不得不使用动态sql。你的月份值实际上是一个字符串 - jan,feb等?或者它被存储为日期?如果代码存储为任一代码,您将不得不对代码进行一些调整,但上面的内容会让您开始。 – Taryn

+0

是否有任何其他直接的方式将行转换为列,反之亦然?因为无论“yourtable”是不是一个简单的表。它是一个有很多条件的复杂查询。我也没有奢望去定义单独的变量和多个语句。我应该能够在一个语句中将列转换为行。 –

0

您可以使用UNPIVOT然后PIVOT
最好是DO QUERY嵌入式SQL 创建带有STUFF功能的月份DISTINCT COLUMS,然后 替换为oMonth IN([2013年1月-2013],[2013年2月],[2013年3月],[2013年4月])
此处核心查询

SELECT 
* 
FROM 
( SELECT  
oMonth, value,col 
from (
select DATENAME(month,oDate) + '-' + CAST(YEAR( oDate) as varchar) as oMonth,  Sales ,Income,Profit 
FROM   SalesSource 
)A 
unpivot 
(
    value for col in (Sales ,Income,Profit) 
) u 

) as sourceTable 
PIVOT 
(
sum(value) 
FOR oMonth IN ([January-2013], [February-2013], [March-2013], [April-2013]) 
) AS PivotTable;