更有效地转动行

时间:2017-02-03 15:49:24

标签: sql sql-server sql-server-2012 pivot

我正在尝试将多个表连接在一起。我尝试加入的其中一个表每个ID数据有数百行。我试图将每个ID约100行转换为列。我尝试使用的值并不总是在同一行。下面是一个例子(我的真实表每个ID有数百行)。 ID 1中的AccNum可能位于NumV列中,但对于ID 2,它可能位于CharV列中。

ID  QType       CharV       NumV
1   AccNum                  10
1   EmpNam      John Inc    0
1   UW          Josh        0
2   AccNum      11
2   EmpNam      CBS         0
2   UW          Dan         0

我使用的原始代码是一个包含数百行的select语句,如下所示:

Max(Case When PM.[QType] = 'AccNum' Then NumV End) as AccNum

此代码在不到10分钟的时间内完成了数百行。但问题是,只从我指定的列中提取值,因此我将始终丢失不同列中的数据。 (在上面的示例中,我将获得AccNum 10,但不是AccNum11,因为它在CharV列中。)

我更新了代码以使用数据透视:

;with CTE
As
(
    Select [PMID], [QType],
        Value=concat(Nullif([CharV],''''),Nullif([NumV],0)) 
        From [DBase].[dbo].[PM]
)

Select C.[ID] AS M_ID
    ,Max(c.[AccNum]) As AcctNum
    ,Max(c.[EmpNam]) As EmpName

依旧......

然后我选择了所有数百行,然后将数据转移到它:

from CTE
pivot (max(Value) for [QType] in ([AccNum],[EmpNam],(more rows)))As c

然而,此代码的问题在于它需要将近2个小时才能运行。

对于我想要实现的目标,是否存在不同的,更有效的解决方案?我需要有第一个代码的速度,但第二个代码的结果。

1 个答案:

答案 0 :(得分:2)

也许您可以使用Concat/NullIf

来减少UNION ALL处理
Select ID,QType,Value=CharV From @YourTable where CharV>''
Union All
Select ID,QType,Value=cast(NumV as varchar(25))  From @YourTable where NumV>0

对于条件聚合方法

无需担心哪个字段,只需引用VALUE

Select [ID]
      ,[Accnum] = Max(Case When [QType] = 'AccNum' Then Value End) 
      ,[EmpNam] = Max(Case When [QType] = 'EmpNam' Then Value End) 
      ,[UW]     = Max(Case When [QType] = 'UW'     Then Value End) 
 From (
        Select ID,QType,Value=CharV From @YourTable where CharV>''
        Union All
        Select ID,QType,Value=cast(NumV as varchar(25))  From @YourTable where NumV>0
     ) A
 Group By ID

对于PIVOT方法

Select [ID],[AccNum],[EmpNam],[UW]
From (
        Select ID,QType,Value=CharV From @YourTable where CharV>''
        Union All
        Select ID,QType,Value=cast(NumV as varchar(25))  From @YourTable where NumV>0
     ) A
 Pivot (max([Value]) For [QType] in ([AccNum],[EmpNam],[UW])) p