用于动态生成列的sql pivot

时间:2013-11-11 12:43:07

标签: c# sql-server-2008

我无法弄清楚如何将行设置为cols或使用pivot来动态生成cols。 有3个表 - tblEmp,tblLeaveType& tblEmpLeaves。结果集现在是

EmpId Name Type Days
--------------------
 1    john  al   5
 1    john  cl   2
 2    smith al   3
 3    jack  sl   4

我想通过以下方式获得它。

EmpId Name    al     cl     sl
--------------------------------
 1    john    5      2     null
 2    smith   3     null   null
 3    jack    null  null   4

离开类型可以动态添加。请检查这里的小提琴 - http://sqlfiddle.com/#!3/6ad02e/1 使用sql server 2008,c#

1 个答案:

答案 0 :(得分:2)

如果您只想使用SQL获取最终结果,那么您可以实现PIVOT功能。在尝试编写动态SQL版本之前,您应该首先编写一个硬编码版本,这样您就可以使基本逻辑正确。

如果您需要将有限数量的types转换为列,那么您可以使用:

select id, name, al, cl, sl
from
(
  select e.id, e.name, lt.type, l.days 
  from tblEmp e
  left outer join tblEmpLeaves l 
    on e.id = l.empId
  left outer join tblLeaveType lt 
    on l.leaveId = lt.Id
) d
pivot
(
  max(days)
  for type in (al, cl, sl)
) piv
order by id;

请参阅SQL Fiddle with Demo

但是如果您将拥有未知数量的值,那么您必须使用动态SQL并将代码放在存储过程中:

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

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

set @query = 'SELECT id, name,' + @cols + ' 
            from 
            (
              select e.id, e.name, lt.type, l.days 
              from tblEmp e
              left outer join tblEmpLeaves l 
                on e.id = l.empId
              left outer join tblLeaveType lt 
                on l.leaveId = lt.Id
            ) x
            pivot 
            (
                max(days)
                for type in (' + @cols + ')
            ) p 
            order by id'

execute sp_executesql @query;

SQL Fiddle with Demo。他们都给你结果:

| ID |  NAME |     AL |     CL |     SL |
|----|-------|--------|--------|--------|
|  1 |  john |      5 |      2 | (null) |
|  2 | smith |      3 | (null) | (null) |
|  3 |  jack | (null) | (null) |      4 |