需要通过引用未分割的列名来使用UNPIVOT来操作字段值

时间:2016-09-23 02:42:45

标签: sql sql-server unpivot

我是stackoverflow的新手,也是UNPIVOT的新手,所以如果答案在某处,我道歉,但我无法找到它 - 也许我不知道如何正确地说出来。也请原谅我对h

缺乏了解

我在表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语句中的值引用列标题?到目前为止我用过:

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

谢谢大家。

2 个答案:

答案 0 :(得分:0)

如果您使用的是SQL Server,那么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实际上实现了横向连接,也可以在其他数据库中使用。

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

答案 1 :(得分:0)

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

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%'

返回

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