简体   繁体   中英

SQL Server query for grouping row as column and getting corresponding designation

I have 2 tables in SQL Server:

Table 1 : Department

DeptId   Dept Name
------------------
1        Software Development
2        Testing
3        Customization

Table 2 : Designation

DesigId  Desig Name  DeptId
---------------------------
 1        TL          1
 2        PL          1
 3        TestEngg    2
 4        SE          3

I want the following output which takes department as column heading and group designation under the corresponding department column,

  Software Development     Testing     Customization
        TL                 TestEngg        SE
        PL             

I tried with the below query but Im able to get only the Id's

 DECLARE @deptcols AS VARCHAR(MAX);
 DECLARE @querystr  AS VARCHAR(MAX);


select @deptcols = STUFF((SELECT distinct ',' + QUOTENAME(Dept_Id) 
              FROM Designation 
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

 set @querystr = 'SELECT ' + @deptcols + ' from 
         (
             select Desig_Name, Dept_Id,Desig_Id
             from Designation
        ) p
        pivot 
        (
           count(Desig_Id) FOR Dept_Id in (' + @deptcols + ')
        ) pv '
 execute(@querystr)

I think PIVOT keyword is what you should use here. PIVOT can be used to transform datasets such that columns become rows.

No need to construct dynamic queries

Take a look at this article: http://archive.msdn.microsoft.com/SQLExamples/Wiki/View.aspx?title=PIVOTData

More info: http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

Your code was so very close. My suggestion when working with PIVOT especially a dynamic version is to write the static version first, then convert it to dynamic sql.

The static version, where you hard-code values is like this:

SELECT [Software Development], [Testing], [Customization]
from 
(
   select d.[Dept Name], 
      s.[Desig Name],
      row_number() over(partition by s.deptid order by s.desigid) rn
   from Designation s
   left join department d
      on s.[DeptId] = d.[DeptId]
) p
pivot 
(
  max([Desig Name]) 
  FOR [Dept Name] in ([Software Development], [Testing], [Customization])
) pv

See SQL Fiddle with Demo . The static version allows you to be sure that the syntax is correct and all values, columns etc are in the right places.

Then once you have the syntax it is easy to convert to the dynamic SQL version:

DECLARE @deptcols AS VARCHAR(MAX)
DECLARE @querystr  AS VARCHAR(MAX)

select @deptcols = STUFF((SELECT  ',' + QUOTENAME([Dept Name]) 
              FROM Department 
              GROUP BY [Dept Name], DeptId
              ORDER BY DeptId
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')

set @querystr = 
      'SELECT ' + @deptcols + ' from 
         (
            select d.[Dept Name], 
                s.[Desig Name],
              row_number() over(partition by s.deptid order by s.desigid) rn
            from Designation s
            left join department d
               on s.[DeptId] = d.[DeptId]
        ) p
        pivot 
        (
           max([Desig Name]) 
           FOR [Dept Name] in (' + @deptcols + ')
        ) pv '

execute(@querystr)

See SQL Fiddle with Demo

Both give the result:

| SOFTWARE DEVELOPMENT |  TESTING | CUSTOMIZATION |
---------------------------------------------------
|                   TL | TestEngg |            SE |
|                   PL |   (null) |        (null) |

You will notice that I added the line row_number() over(partition by s.deptid order by s.desigid) rn to the SELECT statement. This allows you to return more than one Desig Name for each Dept Name , without this you will only return one value.

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