简体   繁体   English

将行转置为sql中的列

[英]transpose rows to columns in sql

I have problem in getting the desired output with the SQL query. 我在通过SQL查询获取所需的输出时遇到问题。

My sql data is as follows: 我的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

I need the output as follows, 我需要如下输出

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

I have seen the examples of pivot and unpivot , in pivot I don't get the column headers as row data, and in unpivot I didn't found an example where I can transpose multiple columns. 我见过的例子pivotunpivot ,在pivot我不明白的列标题行数据,并在unpivot我没有找到一个例子,我可以转多列。 I have another option to get this result in the code. 我还有另一个选择可以在代码中获得此结果。 But I want to know is it possible to get this kind of result in sql? 但是我想知道是否有可能在sql中获得这种结果?

Edit 编辑

The result will give only for 3 or 4 months, not more than that. 结果仅给出3或4个月,不超过3个月。

Update : The first sample data is the actual data which I will get as a result of multiple joins and grouping on multiple tables, which I will store into a temp table. 更新 :第一个示例数据是由于多个联接和对多个表进行分组而获得的实际数据,这些数据将存储到临时表中。 I tried to get the required result by modifying the query which is not possible because of the table structure. 我试图通过修改查询来获得所需的结果,由于表结构的原因,这是不可能的。 I managed to get the result as in the first sample data, but this is not what the client want to see!!! 我设法获得了第一个示例数据中的结果,但这不是客户希望看到的!!! So I need to process the temp table data which will be only 3 to 4 rows into required output. 因此,我需要处理临时表数据,该表将只有3至4行到所需的输出中。 The query to get the first result is select * from temp . 要获得第一个结果的查询是select * from temp The processing needs to be done on temp table result. 需要对temp表结果进行处理。

Update-2 更新2

I have tried the following query 我尝试了以下查询

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;'

Which gave me the first row correctly!!! 正确地给了我第一行!!! But I tried to use union as 但是我试图用union作为

set @query = 
        'select ''TOTAL'' as Data,' +@cols+' from
        (select MonthYear,TOTALCLAIMS from #tmp)st
        pivot
        (
            MAX(TOTAL) for MonthYear in (' + @cols + ')
        )pt;
        union
        select ''CHARGES'' as Data,' +@cols+' from
        (select MonthYear,TOTALCLAIMS from #tmp)st
        pivot
        (
            MAX(CHARGES) for MonthYear in (' + @cols + ')
        )pt;'

Which gives an error as incorrect syntax near union . 这给出了一个错误,因为incorrect syntax near union Any one know how to union pivot results? 有人知道如何结合pivot结果吗? Or is there any better way to do this? 还是有更好的方法来做到这一点?

Thank You. 谢谢。

I have tried this code. 我已经尝试过此代码。 Please check and let me know if it works 请检查并通知我是否可行

I know that it doesnt look so good. 我知道它看起来不太好。 Also not sure how it will be performance wise. 同样也不确定性能如何。

--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

Hope this helps 希望这可以帮助

I would imagine the reason you are only getting 3 or 4 months is because you don't have data for the missing months? 我想您之所以只得到3或4个月的原因是因为您没有缺少月份的数据? If you want to display columns for missing months you will need to either: 如果要显示缺少月份的列,则需要执行以下任一操作:

  1. Create a Table datatype with all the months you want to display and left join the remainder of the tables to it in your query. 使用要显示的所有月份创建一个表数据类型,并将其余表与查询中的其余表连接起来。 You could then use the PIVOT function as normal. 然后,您可以照常使用PIVOT功能。

  2. If you know how many columns up front ie one for each month in a particular year and it won't change, you can simply use CASE Statements (one for each month) to transpose the data without the PIVOT operator. 如果您知道前面有几列,即特定年份的每个月一列,并且不会改变,那么您可以简单地使用CASE语句(每个月一列)来转置数据,而无需使用PIVOT运算符。

I can provide examples if needed. 如果需要,我可以提供示例。

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)

Try Pivot with the above query you may to get required result.... 尝试对上述查询使用Pivot ,以获得所需的结果。...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM