1

我有一张表,由于某种原因,它具有如下硬编码值:

Row ID    QtyC1   QtyC2  QtyC3   QtyC4  QtyN1   QtyN2  QtyN3   QtyN4  
100       10      5      8       9      11      12     5       6
101       9       11     12      5      6       10     4       9

该表有 35 列和大约 12k 条记录(意味着大约 500k 值),并且正在不断添加和修改。

我试图将其转换为:

Row ID  Year  Period  Val
100     C     1       10
100     C     2       5
100     C     3       8
100     C     4       9
100     N     1       11
100     N     2       12
100     N     3       5
100     N     4       6

到目前为止,我已经设法使用此查询将其拆分为单个值:

SELECT Row ID, YP, Val

FROM (SELECT Row ID
    , QtyC1 AS C1
    , QtyC2 AS C2
    , QtyC3 AS C3
    , QtyC4 AS C4
    , QtyN1 AS N1
    , QtyN2 AS N2
    , QtyN3 AS N3
    , QtyN4 AS N4

FROM MyTable
) SUB
UNPIVOT (Val FOR YP IN (C1,C2,C3,C4,N1,N2,N3,N4)) AS PVT

这给了我一个单一的识别值(例如C1),但是我怎样才能分割它,所以我有一个数字句点和一个年份的单个字符(1C)?

我可以看到将字符串分成两部分可能是可能的,但如果可能的话,我希望有一种更清洁的方式。

4

2 回答 2

2

您可以使用, ,等轻松拆分YP字符串。我的建议是您如何处理. 看起来你有很多列,所以我的建议可能是实现动态 SQL 来执行这个查询。你会这样做:LEFT()RIGHT()SUBSTRING()UNPIVOTUNPIVOT

declare @colsUnpivot varchar(max),
  @query  AS NVARCHAR(MAX),
  @cols  varchar(max)

select @colsUnpivot = stuff((select ','
                             +quotename(replace(C.name, 'Qty', ''))
         from sys.columns as C
         where C.object_id = object_id('yourtable') and
               C.name like 'Qty%'
         for xml path('')), 1, 1, '')

select @cols = stuff((select ','
                      +quotename(C.name) + ' as ' + replace(C.name, 'Qty', '')
         from sys.columns as C
         where C.object_id = object_id('yourtable') and
               C.name like 'Qty%'
         for xml path('')), 1, 1, '')

set @query 
  = 'select rowid, 
          left(YP, 1) YP,
          cast(right(YP, len(YP) - 1) as int) period,
          Val
     from
     (
        select rowid, ' + @cols + '
        from yourtable
     ) x1
     unpivot
     (
        val for YP IN (' + @colsUnpivot + ')
     ) u'

exec(@query)

SQL Fiddle with Demo

于 2012-09-24T19:28:36.777 回答
1

为什么这看起来不干净?

SELECT Row ID, left(YP, 1) as year, cast(right(yp, 1) as int) as period, Val
FROM (SELECT Row ID
    , QtyC1 AS C1
    , QtyC2 AS C2
    , QtyC3 AS C3
    , QtyC4 AS C4
    , QtyN1 AS N1
    , QtyN2 AS N2
    , QtyN3 AS N3
    , QtyN4 AS N4
FROM MyTable
) SUB
UNPIVOT (Val FOR YP IN (C1,C2,C3,C4,N1,N2,N3,N4)) AS PVT
于 2012-09-24T17:30:32.017 回答