需要通过引用被反透视的列名来使用 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
我是 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