gpt4 book ai didi

sql - 根据月数将列返回为行

转载 作者:行者123 更新时间:2023-12-03 02:04:16 25 4
gpt4 key购买 nike

这似乎是一件很容易完成的事情,但我不确定我是否正确地考虑它以获得所需的结果。我正在使用枢轴,但我认为我需要其他东西与之搭配。

我有一个发票表,其中包含每个客户的每月发票。客户每年最多有 12 张发票,每月 1 张。

+----------+-------+-------+--------------+--------------+--------------+
| ClientID | Month | Year | ColumnValue1 | ColumnValue2 | ColumnValue3 |
+----------+-------+-------+--------------+--------------+--------------+
| 1 | 1 | 2012 | 20 | 30 | 50 |
| 1 | 2 | 2012 | 25 | 35 | 40 |
| 2 | 1 | 2012 | 28 | 38 | 48 |
+----------+-------+-------+--------------+--------------+--------------+

现在,我想根据每个客户创建一个如下所示的列表。每个月都会有一个专栏。所以客户端 1 看起来像:

+--------------+----+----+---+---+---+---+---+---+---+----+----+----+-------+
| ColumnName | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | Total |
+--------------+----+----+---+---+---+---+---+---+---+----+----+----+-------+
| ColumnValue1 | 20 | 25 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 45 |
| ColumnValue2 | 30 | 35 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 65 |
| ColumnValue3 | 50 | 40 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 90 |
+--------------+----+----+---+---+---+---+---+---+---+----+----+----+-------+

最佳答案

这可以使用 SQL Server 中的 UNPIVOTPIVOT 函数来完成。如果您的列数已知,则可以使用静态版本:

select clientid,
col, year,
isnull([1], 0) [1],
isnull([2], 0) [2],
isnull([3], 0) [3],
isnull([4], 0) [4],
isnull([5], 0) [5],
isnull([6], 0) [6],
isnull([7], 0) [7],
isnull([8], 0) [8],
isnull([9], 0) [9],
isnull([10], 0) [10],
isnull([11], 0) [11],
isnull([12], 0) [12],
(isnull([1], 0) + isnull([2], 0) + isnull([3], 0)
+ isnull([4], 0) + isnull([5], 0) + isnull([6], 0)
+ isnull([7], 0) + isnull([8], 0) + isnull([9], 0)
+ isnull([10], 0) + isnull([11], 0) + isnull([12], 0) ) Total
from
(
select clientid, col, month, year, value
from yourtable
unpivot
(
value for col in (ColumnValue1, ColumnValue2, ColumnValue3)
) u
) x
pivot
(
sum(value)
for month in ([1], [2], [3], [4], [5], [6], [7],
[8], [9], [10], [11], [12])
) p

参见SQL Fiddle with Demo

但是使用动态 sql 来执行此操作可能会容易得多,这样需要编写的代码就会更少,并且这将根据您的数据样本中的内容调整月数:

DECLARE @colsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@colsPivot as NVARCHAR(MAX),
@colsTotal as NVARCHAR(MAX),
@colsNull as NVARCHAR(MAX)

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

select @colsPivot = STUFF((SELECT distinct ', ' + quotename(Month)
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')

select @colsNull = STUFF((SELECT distinct ', IsNull('
+ quotename(Month) + ', 0) as '+quotename(Month)
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')

select @colsTotal = STUFF((SELECT distinct '+ IsNull('
+ quotename(Month) + ', 0)'
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')


set @query
= 'select clientid,
year,
'+@colsNull+', '+@colsTotal+' as Total
from
(
select clientid, col, month, year, value
from yourtable
unpivot
(
value for col in ('+@colsUnpivot+')
) u
) x
pivot
(
sum(value)
for month in('+ @colspivot +')
) p'

exec(@query)

参见SQL Fiddle with Demo

两者都会产生相同的结果,不同之处在于第二个将根据表中的数据进行调整:

| CLIENTID | YEAR |  1 |  2 | TOTAL |
-------------------------------------
| 1 | 2012 | 20 | 25 | 45 |
| 1 | 2012 | 30 | 35 | 65 |
| 1 | 2012 | 50 | 40 | 90 |
| 2 | 2012 | 28 | 0 | 28 |
| 2 | 2012 | 38 | 0 | 38 |
| 2 | 2012 | 48 | 0 | 48 |

关于sql - 根据月数将列返回为行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13022718/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com