在sql中将行转换为列

在sql中将行转换为列,sql,sql-server,sql-server-2008,unpivot,Sql,Sql Server,Sql Server 2008,Unpivot,我无法通过SQL查询获得所需的输出 我的sql数据如下: TOTAL Charge PAYMNET A B C D E MonthYear ------- ----------- ----------- --------- -------- ---------- ------- ------- ---------- 661 157832.24 82967.80 700.00 10

我无法通过SQL查询获得所需的输出

我的sql数据如下:

TOTAL   Charge      PAYMNET      A         B        C          D       E      MonthYear
------- ----------- ----------- --------- -------- ---------- ------- ------- ----------
661     157832.24   82967.80    700.00    10.70    58329.33   0.00    0.00    Oct-2013
612     95030.52    17824.28    850.00    66.10    53971.41   0.00    0.00    Nov-2013
584     90256.35    16732.91    700.00    66.10    52219.87   0.00    0.00    Dec-2013
511     72217.32    12336.12    285.00    53.17    42951.12   0.00    0.00    Jan-2014
我需要如下输出:

Data            Jan-2013            Feb-2013            Mar-2013

TOTALCOUNT      761                 647                 671
Charge          126888              119995              151737.5
Payment         25705.4             26235.47            28704.41
A               1089.08             1020                745
B               2100.4              1947.25             1868.22
C               94246.55            84202.15            115673.7
D               0                   0                   0
E               0                   0                   0
我看过pivot和unpivot的示例,在pivot中我没有将列标题作为行数据获取,在unpivot中我没有找到可以转置多个列的示例。我有另一个选项可以在代码中得到这个结果。但是我想知道,在sql中是否有可能得到这种结果

编辑

结果只会持续3到4个月,不会超过这个时间

更新:第一个示例数据是我将在多个表上进行多个连接和分组后获得的实际数据,我将其存储到临时表中。我试图通过修改查询来获得所需的结果,但由于表结构的原因,这是不可能的。我设法得到了第一个样本数据的结果,但这不是客户想要看到的!!!因此,我需要将只有3到4行的临时表数据处理为所需的输出。获取第一个结果的查询是select*from temp。需要对临时表结果进行处理

更新-2

我尝试了以下查询

declare @cols varchar(max)
select @cols = STUFF((select ', ' + MonthYear
                      from #tmp for xml path('')),1,1,'')

declare @query varchar(max)
set @query = 
        'select ''TOTAL'' as Data,' +@cols+' from
        (select MonthYear,TOTALCLAIMS from #tmp)st
        pivot
        (
            MAX(TOTAL) for MonthYear in (' + @cols + ')
        )pt;'
这给了我正确的第一排!!!但我试着把工会当作

这会导致一个错误,即union附近的语法不正确。有人知道如何合并数据透视结果吗?还是有更好的方法


谢谢。

我想你只有3个月或4个月的时间是因为你没有缺失月份的数据?如果要显示缺少月份的列,则需要:

创建包含要显示的所有月份的表数据类型 并在查询中将剩余的表左键联接到它。你 然后可以正常使用枢轴功能

如果您知道预先准备了多少列,即特定年份中每个月一列,并且它不会改变,那么您可以简单地使用用例 每月一份报表,用于在没有 枢轴操作员

如果需要,我可以提供例子

Select Month(Mdate)md,'A' AS Col,sum(A) as a from Product group by Month(MDate)
union all
Select Month(Mdate)md,'B',sum(b) as a from Product group by Month(MDate)
union all
Select Month(Mdate)md,'C',sum(c) as a from Product group by Month(MDate)
union all
Select Month(Mdate)md,'D',Count(A) as a from Product group by Month(MDate)

使用上面的查询尝试Pivot,您可能会得到所需的结果……

我已经尝试了此代码。请检查并让我知道它是否有效

我知道它看起来不太好。也不确定它的性能如何

--Can have more columns like A,B,...
DECLARE @tbl TABLE
(
TOTAL INT,
CHARGE FLOAT,
PAYMENT FLOAT,
MONTHYEAR VARCHAR(50)
)


--Test data
INSERT INTO @tbl SELECT 661, 157832.24, 82967.80, 'Oct2013'
INSERT INTO @tbl SELECT 612,     95030.52,    17824.28, 'Nov2013'
INSERT INTO @tbl SELECT 584     ,90256.35,    16732.91, 'Dec2013'

--Can be a physical table
CREATE TABLE #FinalTbl 
(
DATA VARCHAR(100)
)

--inserted hardcode records in data column. To add it dynamically you would need to loop through information_schema.columns
--SELECT *
--FROM information_schema.columns
--WHERE table_name = 'tbl_name'
INSERT INTO #FinalTbl
VALUES ('TOTAL')

INSERT INTO #FinalTbl
VALUES ('CHARGE')

INSERT INTO #FinalTbl
VALUES ('PAYMENT')

DECLARE @StartCount INT, @TotalCount INT, @Query VARCHAR(5000), @TOTAL INT,@CHARGE FLOAT,@PAYMENT FLOAT,@MONTHYEAR VARCHAR(50)

SELECT @TotalCount = COUNT(*) FROM @tbl;
SET @StartCount = 1;

WHILE(@StartCount <= @TotalCount)
BEGIN
    SELECT @TOTAL = TOTAL, 
    @CHARGE = CHARGE,
    @PAYMENT = PAYMENT,
    @MONTHYEAR = MONTHYEAR  
    FROM
    (SELECT ROW_NUMBER() over(ORDER BY MONTHYEAR) AS ROWNUM, * FROM @tbl) as tbl
    WHERE ROWNUM = @StartCount

    SELECT @Query = 'ALTER TABLE #FinalTbl ADD ' + @MONTHYEAR + ' VARCHAR(1000)'
    EXEC (@Query)

    SELECT @Query = 'UPDATE #FinalTbl SET ' + @MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), @TOTAL) + ''' WHERE DATA = ''TOTAL'''
    EXEC (@Query)

    SELECT @Query = 'UPDATE #FinalTbl SET ' + @MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), @CHARGE) + ''' WHERE DATA = ''CHARGE'''
    EXEC (@Query)

    SELECT @Query = 'UPDATE #FinalTbl SET ' + @MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), @PAYMENT) + ''' WHERE DATA = ''PAYMENT'''
    EXEC (@Query)

    SELECT @StartCount = @StartCount + 1
END

SELECT * FROM #FinalTbl

DROP TABLE #FinalTbl

希望这有帮助

您是否会在同一个月内有多个记录?如果是,那么应该如何处理它们?请指定。@samar No。我在同一个月和同一年中不会有多条记录。这可能会有所帮助,但并非微不足道。另一种方法是在表中循环并创建所需的表。但这并不容易,无论是编码还是性能都是如此。请在每个月之前删除分号,因为没有遗漏月份。仅重新提交3或4个月的数据。我在问题中显示的是一个示例数据。请显示您的查询以提供帮助。我给出的结果是我在临时表中得到的结果。我无法更改主查询[我不允许:]及其太大的查询。上面的查询是select*from tmp。你能不能也发布pivot查询作为结果。此查询单独运行良好。但当我在我的过程中实现了相同的方法时,除了数据列之外,它在所有列中都显示空值。非常感谢。
--Can have more columns like A,B,...
DECLARE @tbl TABLE
(
TOTAL INT,
CHARGE FLOAT,
PAYMENT FLOAT,
MONTHYEAR VARCHAR(50)
)


--Test data
INSERT INTO @tbl SELECT 661, 157832.24, 82967.80, 'Oct2013'
INSERT INTO @tbl SELECT 612,     95030.52,    17824.28, 'Nov2013'
INSERT INTO @tbl SELECT 584     ,90256.35,    16732.91, 'Dec2013'

--Can be a physical table
CREATE TABLE #FinalTbl 
(
DATA VARCHAR(100)
)

--inserted hardcode records in data column. To add it dynamically you would need to loop through information_schema.columns
--SELECT *
--FROM information_schema.columns
--WHERE table_name = 'tbl_name'
INSERT INTO #FinalTbl
VALUES ('TOTAL')

INSERT INTO #FinalTbl
VALUES ('CHARGE')

INSERT INTO #FinalTbl
VALUES ('PAYMENT')

DECLARE @StartCount INT, @TotalCount INT, @Query VARCHAR(5000), @TOTAL INT,@CHARGE FLOAT,@PAYMENT FLOAT,@MONTHYEAR VARCHAR(50)

SELECT @TotalCount = COUNT(*) FROM @tbl;
SET @StartCount = 1;

WHILE(@StartCount <= @TotalCount)
BEGIN
    SELECT @TOTAL = TOTAL, 
    @CHARGE = CHARGE,
    @PAYMENT = PAYMENT,
    @MONTHYEAR = MONTHYEAR  
    FROM
    (SELECT ROW_NUMBER() over(ORDER BY MONTHYEAR) AS ROWNUM, * FROM @tbl) as tbl
    WHERE ROWNUM = @StartCount

    SELECT @Query = 'ALTER TABLE #FinalTbl ADD ' + @MONTHYEAR + ' VARCHAR(1000)'
    EXEC (@Query)

    SELECT @Query = 'UPDATE #FinalTbl SET ' + @MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), @TOTAL) + ''' WHERE DATA = ''TOTAL'''
    EXEC (@Query)

    SELECT @Query = 'UPDATE #FinalTbl SET ' + @MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), @CHARGE) + ''' WHERE DATA = ''CHARGE'''
    EXEC (@Query)

    SELECT @Query = 'UPDATE #FinalTbl SET ' + @MONTHYEAR + ' = ''' + CONVERT(VARCHAR(50), @PAYMENT) + ''' WHERE DATA = ''PAYMENT'''
    EXEC (@Query)

    SELECT @StartCount = @StartCount + 1
END

SELECT * FROM #FinalTbl

DROP TABLE #FinalTbl