简体   繁体   中英

How do you transpose rows into columns in a SQL query

I have this output:

Contact_Type    Category_Type        Category_Count
---------------------------------------------------
Window          Admissions              1775
Window          Financial Aid          17377
Window          Miscellaneous           2720
Window          Student Financials     14039
Phone           Admissions              5758
Phone           Financial Aid          10048
Phone           Miscellaneous           4497
Phone           Registration              11
Phone           Student Financials      4857

and this is my query:

SELECT 
    Contact_Type, Category_Type1, Category_Type2, Category_Type3,
    Category_Type4, Category_Type5 
FROM
    (SELECT 
         CASE
            WHEN event.contact_type = 0 THEN 'Window' 
            WHEN event.contact_type = 1 THEN 'Phone' 
         END AS Contact_Type,
         cat.category_type AS Category_Type,
         COUNT(ec.category_id) AS Category_Count,
         'Category_Type' + CAST(ROW_NUMBER() OVER (PARTITION BY Contact_Type
ORDER BY Contact_Type) AS varchar(20)) AS ColumnSequence
     FROM 
         yLines.ylines_event AS Event
     JOIN 
         ylines.ylines_event_category AS ec ON ec.event_id = event.event_id
     JOIN 
         ylines.ylines_category AS cat ON ec.category_id = cat.category_id
     WHERE /*event.contact_type = '0' AND*/    
         CAST(FORMAT(event.event_date_time, 'yyyy') AS int) BETWEEN 2014 AND dateadd(year, 1, event.event_date_time)
     GROUP BY 
         Category_Type, Contact_Type) a 
PIVOT
    (MAX(Contact_Type)
     FOR ColumnSequence IN (Category_Type1, Category_Type2, Category_Type3,
Category_Type4, Category_Type5)) as piv;   

If I run this it gives me an error:

Msg 207, Level 16, State 1, Line 1
Invalid column name 'Contact_Type'

and I can't seem to fix this. I am trying to transpose it so I see two rows only with 'Windows' and 'Phone' and the five Category Types transposed as five columns with the count in each. I am writing T-SQL statements. Please help!

In the group by clause you say

`group by Category_Type, Contact_Type`

However, you have defined a calculated column as contact_type which is not available in the group by clause. You should use

GROUP BY Category_Type, -- Contact_Type
case 
when event.contact_type=0 then 'Window' 
when event.contact_type=1 then 'Phone' 
end 

It is a better approach to name your calculated columns different than the columns in any of your tables.

Use case statements for pivoting:

SELECT CONTACT_TYPE,
SUM(CASE WHEN CATEGORY_TYPE='Admissions' THEN CATEGORY_COUNT END) ADMISSIONS,
SUM(CASE WHEN CATEGORY_TYPE='Financial Aid' THEN CATEGORY_COUNT END) FINANCIAL_AID,
SUM(CASE WHEN CATEGORY_TYPE='Miscellaneous' THEN CATEGORY_COUNT END) MISCELLANEOUS,
SUM(CASE WHEN CATEGORY_TYPE='Student Financials' THEN CATEGORY_COUNT END) STUDENT_FINANCIALS,
SUM(CASE WHEN CATEGORY_TYPE='Registration' THEN CATEGORY_COUNT END) REGISTRATION
FROM TEST_3 GROUP BY CONTACT_TYPE;

Output:

CONTACT_TYPE    ADMISSIONS  FINANCIAL_AID   MISCELLANEOUS   STUDENT_FINANCIALS  REGISTRATION
 Phone             5758         10048           4497               4857                11
 Window            1775         17377           2720              14039              null

I would try do it in dynamic

       ; WITH [CONTACT]
     AS (
         SELECT *
           FROM (
                 VALUES 
                        ('Window', 'Admissions        ', ' 1775')
                      , ('Window', 'Financial Aid     ', '17377')
                      , ('Window', 'Miscellaneous     ', ' 2720')
                      , ('Window', 'Student Financials', '14039')
                      , ('Phone ', 'Admissions        ', ' 5758')
                      , ('Phone ', 'Financial Aid     ', '10048')
                      , ('Phone ', 'Miscellaneous     ', ' 4497')
                      , ('Phone ', 'Registration      ', '   11')
                      , ('Phone ', 'Student Financials', ' 4857')
                ) X ([Contact_Type], [Category_Type], [Category_Count])
     )   


     SELECT * 
       INTO #TEMP_PIVOT
       FROM [CONTACT]

    DECLARE @TYPE    VARCHAR(MAX)   
        SET @TYPE = STUFF( 
                          (SELECT DISTINCT ', ' + QUOTENAME(RTRIM(LTRIM([CATEGORY_TYPE])))
                                    FROM #TEMP_PIVOT
                                     FOR XML PATH('')
                          )
                          , 1, 1, '')

   DECLARE @SQL    VARCHAR(MAX)
       SET @SQL = '  SELECT [CONTACT_TYPE] '
                + '       , ' + @TYPE
                + '    FROM #TEMP_PIVOT '
                + '   PIVOT ( '
                + '           MAX([CATEGORY_COUNT]) '
                + '           FOR [CATEGORY_TYPE] IN (' + @TYPE + ')'
                + '         ) P '

     EXECUTE (@SQL)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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