T-SQL Query基于多个表将行转换为列

时间:2011-10-19 06:30:03

标签: tsql sql-server-2008 pivot

我有两个主表CompanyMasterActivityMaster用于子表CompanyActivities

ActivityMaster

ACTIVITYID   ACTIVITYNAME
A1           testActivity
A2           someActivity
A3           otheractivity
A4           someotheractivity
A5           anyotheractivity

CompanyMaster

COMPANYID  COMPANYNAME
C1         testcompany
C2         ACompany
C3         MyCompany
C4         SomeCompany
C5         ZCompany
C6         Company123
C7         ComapnyABC

CompanyActivities - COMPANYID中的CompanyActivitiesCOMPANYID(主要密钥表)和{{1}中与CompanyMaster建立了主键 - foreighkey关系在ACTIVITYID(主键表)中有ACTIVITYID的primarykey-foreighkey关系

ActivityMaster

我想编写一个查询来获取以下输出,其中COMPANYID ACTIVITYID C1 A1 C1 A3 C3 A1 C3 A2 C4 A5 C5 A1 C6 A3 C7 A3 表的ACTIVITYID列中的所有行都将转换为列

输出

ActivityMaster

输出表将所有公司显示为第一列中的行,并且所有活动都显示为在第一列之后开始的列,如果有行包含Companies A1 A2 A3 A4 A5 C1 Y N Y N N C2 N N N N N C3 Y Y N N N C4 N N N N Y C5 Y N N N N C6 N N Y N N C7 N N Y N N ACTIVITYID的行将在输出中设置为COMPANYID,否则将设置为Y

例如 - N COMPANYIDC1表中有一个活动ACTIVITYID A1,因此第二列中的第一行位于CompanyActivities下方1}}和A1的右侧设置为C1,而YC1没有行,因此第一行中的第三列设置为A2

我正在使用C#.net和4 for循环来实现输出现在正在对应用程序的性能造成严重影响,所以我想使用查询来执行此操作,我已经搜索了数据透视查询,但是我找到的所有示例都知道前面的列名,我不会通过查询N来获取列名的名称。

1 个答案:

答案 0 :(得分:2)

create table #CompanyMaster (COMPANYID int, COMPANYNAME varchar(30))
create table #ActivityMaster (ACTIVITYID int, ACTIVITYNAME varchar(30))
create table #CompanyActivities (COMPANYID int, ACTIVITYID int)

insert into #CompanyMaster
    SELECT 1, 'Company A'
    union all
    SELECT 2, 'Company B'

insert into #ActivityMaster
    SELECT 101, 'Activity X'
    union all
    SELECT 102, 'Activity Y'    
    union all
    SELECT 103, 'Activity Z'    

insert into #CompanyActivities      
    select 1, 102
    union all
    select 2, 101

-- build activities column names
--case [Activity X] when 0 then ''N'' else ''Y'' end as [Activity X],
--case [Activity Y] when 0 then ''N'' else ''Y'' end as [Activity Y],
--case [Activity Z] when 0 then ''N'' else ''Y'' end as [Activity Z]
declare @activities nvarchar(max)
set @activities
   = (
    select 'case [' + ACTIVITYNAME + '] when 0 then ''N'' else ''Y'' end as [' + ACTIVITYNAME + '],' + char(10)
    from #ActivityMaster
    for xml path('')
   )
set @activities = substring(@activities, 0, len(@activities)-1)

declare @activities_for nvarchar(max)
-- build activities column names in for
--[Activity X], [Activity Y], [Activity Z]
set @activities_for
   = (
    select '[' + ACTIVITYNAME + '],' + char(10)
    from #ActivityMaster
    for xml path('')
   )
set @activities_for = substring(@activities_for, 0, len(@activities_for)-1)


declare @sql nvarchar(MAX) = N'
select COMPANYNAME,
    <activities>
From
    (select c.COMPANYNAME, a.ACTIVITYNAME,
        (case 
            when ca.ACTIVITYID is not null and ca.COMPANYID is not null then 1
            else 0
        end) as STATUS
    from #CompanyMaster c
    cross join #ActivityMaster a
    left join #CompanyActivities ca on ca.COMPANYID = c.COMPANYID and a.ACTIVITYID = ca.ACTIVITYID)  p
pivot
    (
        sum(STATUS) for ACTIVITYNAME IN (<activities_for>)
    ) as pvt
'


set @sql = replace(@sql, '<activities>', @activities)
set @sql = replace(@sql, '<activities_for>', @activities_for)

print @sql
exec sp_executesql @sql

drop table #CompanyMaster
drop table #ActivityMaster
drop table #CompanyActivities