T-SQL 查询根据多个表将行转换为列

发布于 2024-12-11 06:18:40 字数 1983 浏览 4 评论 0原文

我有两个主表 CompanyMaster,一个子表 CompanyActivities

ActivityMaster 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 - CompanyActivities 中的 COMPANYID 与中的 COMPANYID 具有主键-外键关系CompanyMaster(主键表)和 ACTIVITYIDActivityMaster 中的 ACTIVITYID 具有主键-外键关系(主键表) key 表)

COMPANYID   ACTIVITYID
C1          A1
C1          A3
C3          A1
C3          A2
C4          A5
C5          A1
C6          A3
C7          A3

我想编写一个查询来获取以下输出,其中 ActivityMaster 表的 ACTIVITYID 列中的所有行都将转换为列

输出

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

输出表显示所有公司作为第一列中的行和所有活动都显示为从第一列之后开始的列,如果有行同时包含 ACTIVITYIDCOMPANYID ,它将设置为 Y 在输出中,否则它将被设置为 N

例如 - COMPANYID C1 有一个活动 ACTIVITYID A1CompanyActivities 表,因此位于 A1 下方且位于 C1 右侧的第二列中的第一行设置为 Y,而 C1A2 没有一行,因此第一行中的第三列设置为 N

我正在使用 C# .net 和 4 个 for 循环来实现现在正在谈论的输出对应用程序的性能造成沉重负担,所以我想使用查询来执行此操作,我搜索了枢轴查询,但我发现的所有示例都事先知道列名称,但我不知道,我只得到通过查询ActivityMaster来获取列名。

I have two master tables CompanyMaster, ActivityMaster for a child table 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 - The COMPANYID in CompanyActivities is having a primarykey-foreighkey relation ship with COMPANYID in CompanyMaster (primary key table) and ACTIVITYID is having a primarykey-foreighkey relation ship with ACTIVITYID in ActivityMaster(primary key table)

COMPANYID   ACTIVITYID
C1          A1
C1          A3
C3          A1
C3          A2
C4          A5
C5          A1
C6          A3
C7          A3

I want to do write a query to get the following output where all the rows in ACTIVITYID column of the ActivityMaster table will be converted to columns

Output

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

The output table displays all the companies as rows in the first column and all the activities are shown as columns that start after the first column, if there is row that contains both ACTIVITYID and COMPANYID it will set to Y in output otherwise it would be set to N

eg- COMPANYID C1 is having an activity ACTIVITYID A1 in CompanyActivities table so the first row in the second column that comes just below A1 and in the right to C1 is set Y, whereas C1 and A2 are not having a row, so the third column in the first row is set to N

I am using C#.net and 4 for loops to achieve the output now which is talking a heavy toll on the performance of the application, So i would like to do this using a query, I have searched for pivot queries, but all the examples i found knows the column names before-hand, which i don't i only get the names of the column names by querying the ActivityMaster.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

玉环 2024-12-18 06:18:40
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
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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文