用于将行转换为列

时间:2017-06-22 14:01:24

标签: asp.net sql-server-2008

我有一个使用SQL Server 2008的.net Web应用程序。我试图在网格中显示的数据表包含实际上是另一个表的行的列。现在,我在BLL中这样做,将数据读入数据表;从另一个表中获取数据并将其放入第一个数据表的列中,然后遍历该数据表中的每一行数据以填充新列。非常耗时且缓慢。

我相信这可以通过SQL 2012及更高版本中的查询使用“Transpose”或类似的东西来完成,但不确定它是否可能在2008年。我研究并尝试使用“pivot”但我不擅长SQL和无法让它发挥作用。

这是数据库表的简化示例以及我需要显示的内容:

Facility Table:
FacilityID
12345
67890

PartnerInfo table:
PartnerID    Partner
1            Partner1
2            Partner2
3            Partner3

FacilityPartner table:
FacilityID    PartnerID
12345         1
12345         3
67890         2
67890         3

需要查询才能返回以下内容:

FacilityID    Partner1    Partner2    Partner3
12345         true        false       true
67890         false       true        true

2 个答案:

答案 0 :(得分:1)

首先要理解的是,就像许多其他语言一样,SQL有一种"编译"进程,生成执行计划。 SQL查询必须能够在不引用数据的情况下知道编译时列的精确数量和类型(它确实有一些表元数据可用于编译,这就是为什么SELECT *有效的原因。

这意味着只有满足以下两个条件之一才能实现您的目标:

  1. 您必须提前知道合作伙伴的确切数量(以及列的名称,在本例中)。即使对于使用PIVOT关键字的查询也是如此。
  2. 您必须愿意使用动态SQL在多个步骤中执行此操作,其中第一步是查看数据以了解您需要多少列。然后,您可以在varchar变量中构建新查询,最后使用Exec()sp_executesql()执行该字符串。这是有效的,因为最后一步调用了一个新的"编译"该字符串变量的进程和执行上下文。
  3. 当然还有第三种选择:在您的客户端代码中转动数据。这是我的偏好。但是,大多数人选择选项2。

答案 1 :(得分:1)

以下内容应该对转动数据有所了解。如你所说,它并没有给你准确的真假。

    declare  @facility table (facilityId int)
    declare  @PartnerInfo  table (partnerid int, partnerN varchar(1000))
    declare  @FacilityPartner table (facilityId int,partnerid int)

    insert into @facility values (12345)
    insert into @facility values (67890)
    insert into @facility values (67891)

    insert into @PartnerInfo values (1, 'partner1')
    insert into @PartnerInfo values (2, 'partner2')
    insert into @PartnerInfo values (3, 'partner3')

    insert into @FacilityPartner values(12345, 1)
    insert into @FacilityPartner values(12345, 3)
    insert into @FacilityPartner values(67890, 2)
    insert into @FacilityPartner values(67890, 3)

    select f.facilityId as facid, p.PartnerN as partn, 100 as val
    FROM @facility f
    LEFT join @FacilityPartner fp on f.facilityId = fp.facilityId
    LEFT JOIN @PartnerInfo p on p.partnerid = fp.partnerid

    select facid, Partner1 , partner2,partner3 FROM 

    (select f.facilityId as facid, p.PartnerN as partn, 100 as val
    FROM @facility f
    LEFT join @FacilityPartner fp on f.facilityId = fp.facilityId
    LEFT JOIN @PartnerInfo p on p.partnerid = fp.partnerid) x
    PIVOT(
    avg(val)
    for partn in ([partner1], [partner2],[partner3])
    ) as pvt