需要通过引用被反透视的列名来使用 UNPIVOT 操作字段值

Need to manipulate field values using UNPIVOT by referencing the column names being unpivoted

我是 Whosebug 的新手和 UNPIVOT 的新手,所以如果答案在那里,我深表歉意,但我找不到它 - 也许我不知道如何正确地表达它。还请见谅我对h

的认识不足

我在 table BUDGET_INFO 中有值,每个月的财务信息都在一行中。

BUD_PROJ    BUD_ACCT   BUD_SUB_ACCT    BUD_YEAR    BUD_MONTH_01    BUD_MONTH_02    BUD_MONTH_03   
1           10000      01              2015        1000            2000            3000

我是这样得到的

BUD_PROJ    BUD_ACCT   BUD_SUB_ACCT    BUD_YEAR   AMOUNT
1           1000       01              2015       1000
1           1000       01              2015       2000
1           1000       01              2015       3000

问题是,我需要知道这些值来自哪个月份。最终结果需要是:

BUD_PROJ    BUD_ACCT   BUD_SUB_ACCT    BUD_YEAR    VALUE
1           1000       01              201501      1000
1           1000       01              201502      2000
1           1000       01              201503      3000

并非所有每月的列值都会被填充,所以我希望能够引用列名并提取月份标识符('01'、'02'、'03' 等)并将其连接起来使用年份值(理想情况下)或仅放入其自己的列中。有什么方法可以从 select 语句中的值引用列 header 吗?到目前为止我使用了:

SELECT
  UNPVT.BUD_PROJ,
  UNPVT.BUD_YEAR,
  UNPVT.BUD_ACCT,
  UNPVT.BUD_SUB_ACCT,
  UNPVT.VALUE
FROM BUDGET_INFO
UNPIVOT 
(
VALUE FOR ATTRIBUTE IN 
(BUD_MONTH_01, BUD_MONTH_02, BUD_MONTH_03,BUD_MONTH_04, BUD_MONTH_05, BUD_MONTH_06, BUD_MONTH_08, BUD_MONTH_09, BUD_MONTH_10, BUD_MONTH_11, BUD_MONTH_12)
) UNPVT
WHERE UNPVT.VALUE != 0

谢谢大家

如果您使用的是 SQL 服务器,那么 apply 可以很容易地做您想做的事:

select bi.BUD_PROJ, bi.BUD_YEAR, bi.BUD_ACCT, bi.BUD_SUB_ACCT,
       v.value. v.mon
from budget_info bi cross apply
     (values (BUD_MONTH_01, 1),
             (BUD_MONTH_02, 2),
             . . . 
     ) v(value, mon))
where v.value <> 0;

apply实际上实现了横向连接,其他数据库也可以使用。

如果你不使用应用,你可以用一堆 union all 做一些非常相似的事情,每个子查询选择一个列。

另一个选项是。 (我添加了第二个虚拟样本记录来说明)

Declare @YourTable table (BUD_PROJ int,BUD_ACCT varchar(25),BUD_SUB_ACCT varchar(25),BUD_YEAR int,BUD_MONTH_01 int,BUD_MONTH_02 int,BUD_MONTH_03 int)
Insert Into @YourTable values
(1,'10000','01',2015,1000,2000,3000),
(2,'11000','01',2015,4000,5000,6000)

Declare @XML xml = (Select * from @YourTable for XML RAW)

Select BUD_PROJ    = r.value('@BUD_PROJ','int')
      ,BUD_ACCT    = r.value('@BUD_ACCT','varchar(25)')
      ,BUD_SUB_ACCT= r.value('@BUD_SUB_ACCT','varchar(25)')
      ,BUD_YEAR    = r.value('@BUD_YEAR','varchar(25)')+right(attr.value('local-name(.)','varchar(100)'),2)
      ,Value = attr.value('.','varchar(max)') 
 From  @XML.nodes('/row') as A(r)
 Cross Apply A.r.nodes('./@*[local-name(.)!="BUD_PROJ"]') as B(attr)
 Where attr.value('local-name(.)','varchar(100)') Like 'BUD_MONTH%'

Returns

BUD_PROJ    BUD_ACCT    BUD_SUB_ACCT    BUD_YEAR    VALUE
1           10000       01              201501      1000
1           10000       01              201502      2000
1           10000       01              201503      3000
2           11000       01              201501      4000
2           11000       01              201502      5000
2           11000       01              201503      6000