我正在努力重新格式化查询中的答案集。这是来自监测工具的数据,我正在计算月平均值以及线性回归预测。这一切都在其他功能中执行并且工作正常。这些函数都使用我使用的最终数据提供以下两个表。我目前唯一要解决的问题是重新格式化输出以显示比行更多的列。
首先,让我向您提供我正在使用的示例数据使用SQL Server 2008R2
create table finalactual(Target varchar(100), MonthNum int, [Actual] real)
create table finalprojection(Target varchar(100), MonthNum int, [monthname] varchar(20), [Forecast] real)
Insert into finalprojection values ('C:\', 2, 'February', 65609.29)
Insert into finalprojection values ('C:\', 3, 'March', 65850.27)
Insert into finalprojection values ('C:\', 4, 'April', 66091.26)
Insert into finalprojection values ('C:\', 5, 'May', 66332.25)
Insert into finalprojection values ('C:\', 6, 'June', 66573.23)
Insert into finalprojection values ('C:\', 7, 'July', 66814.22)
Insert into finalprojection values ('C:\', 8, 'August', 67055.2)
Insert into finalprojection values ('C:\', 9, 'September', 67296.19)
Insert into finalprojection values ('C:\', 10, 'October', 67537.17)
Insert into finalprojection values ('C:\', 11, 'November', 67778.16)
Insert into finalprojection values ('C:\', 12, 'December', 68019.14)
Insert into finalprojection values ('C:\', 13, 'January', 68260.13)
Insert into finalprojection values ('E:\', 2, 'February', 385251.0)
Insert into finalprojection values ('E:\', 3, 'March', 401171.1)
Insert into finalprojection values ('E:\', 4, 'April', 417091.2)
Insert into finalprojection values ('E:\', 5, 'May', 433011.3)
Insert into finalprojection values ('E:\', 6, 'June', 448937.3)
Insert into finalprojection values ('E:\', 7, 'July', 464851.4)
Insert into finalprojection values ('E:\', 8, 'August', 480771.4)
Insert into finalprojection values ('E:\', 9, 'September', 496691.5)
Insert into finalprojection values ('E:\', 10, 'October', 512611.6)
Insert into finalprojection values ('E:\', 11, 'November', 528531.6)
Insert into finalprojection values ('E:\', 12, 'December', 544451.8)
Insert into finalprojection values ('E:\', 13, 'January', 560371.8)
Insert into finalactual values ('C:\', 2, 62927.88)
Insert into finalactual values ('C:\', 3, 64534.62)
Insert into finalactual values ('C:\', 4, 67215.3)
Insert into finalactual values ('C:\', 5, 70991.05)
Insert into finalactual values ('C:\', 6, 69857.11)
Insert into finalactual values ('C:\', 7, 64440.7)
Insert into finalactual values ('C:\', 8, 64359.08)
Insert into finalactual values ('E:\', 2, 382691.4)
Insert into finalactual values ('E:\', 3, 400543.9)
Insert into finalactual values ('E:\', 4, 418160.4)
Insert into finalactual values ('E:\', 5, 435643.2)
Insert into finalactual values ('E:\', 6, 451213.5)
Insert into finalactual values ('E:\', 7, 466608.2)
Insert into finalactual values ('E:\', 8, 476218.2)
如果您运行以下查询
select a.target, a.monthnum as 'Month Value', case when a.monthnum <= 12 then
a.monthnum else a.monthnum-12 end as 'Month Number', a.monthname as [Month],
b.Actual as 'Actual', a.forecast from finalprojection a
left join
finalactual b on a.Target = b.Target AND a.monthnum = b.MonthNum
order by Target ASC, [Month Value] ASC
结果答案集如下所示:
target Month Value Month Number Month Actual forecast
C:\ 2 2 February 62927.88 65609.29
C:\ 3 3 March 64534.62 65850.27
C:\ 4 4 April 67215.3 66091.26
C:\ 5 5 May 70991.05 66332.25
C:\ 6 6 June 69857.11 66573.23
C:\ 7 7 July 64440.7 66814.22
C:\ 8 8 August 64359.08 67055.2
C:\ 9 9 September NULL 67296.19
C:\ 10 10 October NULL 67537.17
C:\ 11 11 November NULL 67778.16
C:\ 12 12 December NULL 68019.14
C:\ 13 1 January NULL 68260.13
E:\ 2 2 February 382691.4 385251
E:\ 3 3 March 400543.9 401171.1
E:\ 4 4 April 418160.4 417091.2
E:\ 5 5 May 435643.2 433011.3
E:\ 6 6 June 451213.5 448931.3
E:\ 7 7 July 466608.2 464851.4
E:\ 8 8 August 476218.2 480771.4
E:\ 9 9 September NULL 496691.5
E:\ 10 10 October NULL 512611.6
E:\ 11 11 November NULL 528531.6
E:\ 12 12 December NULL 544451.8
E:\ 13 1 January NULL 560371.8
这很好,因为我有6个月或7个月的实际数据,结合线性回归计算延长了6个月(这就是为什么9月到1月的“空”值)实际上。
我希望输出的内容是这一行:
Target A/F Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan
C:\ A 62927 64534 67215 70991 69857 64440 64359 NULL NULL NULL NULL NULL
C:\ F 65609 65850 66091 66332 66573 66814 67055 67296 67537 67778 68019 68260
出于空间原因,我已将小数与A / F(意味着实际与预测)缩写。为了简洁起见,我也再次离开E:\驱动器......
可能存在问题的一个问题是,起始月份(在上面的示例中,它是2月)将是动态的。意思是如果查询在9月运行,第一个月将是3月... 10月将4月作为第一个月...依此类推。
我创建了一个SQL小提琴:http://www.sqlfiddle.com/#!3/901c4/1为你们节省了一些时间。
我提前感谢你们的帮助。
与滑动日期需求相关的更新信息:
大家好......所有优秀的解决方案。
让我解释一下我在开始月份的意思。
今天(8月)运行报告需要将结果集的第一个月设置为二月并且结束于2015年1月。这是因为报告可以追溯到历史记录的6个月以收集月度结果。从那里,它延伸(线性回归)超过实际数据另外6个月(预测)。这是我真正需要适应的一个怪癖(我知道......屁股上的痛苦)。
因此,如果此查询将在下个月(9月)运行,则开始月份需要为3月,并在2015年2月结束。如果我在10月份运行报告,则开始月份需要为4月,这将是增加到2015年5月。我希望澄清如何提出月份的滑动规模。
只需添加有关如何使用月份比例的说明: 列“月值”是输出以必要顺序显示的方式。此列将从开始月份开始递增,并继续12个增量。例如: 如果查询在8月份运行(如上面的示例数据),则数据的起始月份为2月(运行日期为“月份值”,8个数据开始于6个月前或“月值”为2个。这将设置命令你看到上面的“月值”开始于答案集2和继续13.生成这些表的部分例程评估“月份值”列并生成“月号”列(如果它是&lt; 12然后使用原始值...如果&gt; 12然后减去12)。这就是为什么“月份值”为13的行显示“月份数”为1,使用datename()转换返回“一月”。 如果要在下个月(9月或10月)运行相同的查询,则答案集中的所有内容都将移1。起始的“月份值”将是3或3月,结束的“月份值”将是14或2月(系统将从超过12的值中减去12以得到2)。在这种情况下,返回的答案集如下所示:
target Month Value Month Number Month Actual forecast
C:\ 3 3 March 62927.88 65609.29
C:\ 4 4 April 64534.62 65850.27
C:\ 5 5 May 67215.3 66091.26
C:\ 6 6 June 70991.05 66332.25
C:\ 7 7 July 69857.11 66573.23
C:\ 8 8 August 64440.7 66814.22
C:\ 9 9 Sept 64359.08 67055.2
C:\ 10 10 October NULL 67296.19
C:\ 11 11 November NULL 67537.17
C:\ 12 12 December NULL 67778.16
C:\ 13 1 January NULL 68019.14
C:\ 14 2 February NULL 68260.13
注意:为了简洁起见,删除了E:\驱动器
旋转的答案应如下所示:
Target A/F Mar Apr May Jun Jul Aug Sep Oct Nov Dec Jan Feb
C:\ A 62927 64534 67215 70991 69857 64440 64359 NULL NULL NULL NULL NULL
C:\ F 65609 65850 66091 66332 66573 66814 67055 67296 67537 67778 68019 68260
看到输出的人不需要看多年,因为他们知道报告显示了12个月的实际和预测数据......所以当“1月”出现时,他们知道他们正在跨越进入新的一年。
我希望这有助于您了解答案集的结构。
再次......感谢您当前的想法...非常好的东西。
答案 0 :(得分:7)
虽然其他两个答案可以得到你想要的结果,但我应该做的略有不同。您可以先unpivot
和Actual
列中Forecast
数据,然后转动月份。
您没有指定正在使用的SQL Server版本,但从SQL Server 2005+开始,您可以使用CROSS APPLY
进行取消隐藏。
基本语法类似于:
select a.target,
Left(a.monthname, 3) as [Month],
AorF,
value
from finalprojection a
left join finalactual b
on a.Target = b.Target
AND a.monthnum = b.MonthNum
cross apply
(
select 'A', b.Actual union all
select 'F', a.forecast
) c(AorF, value);
见Demo。这会将您的多列Actual
和Forecast
转换为多行。一旦数据采用这种格式,您就可以轻松地调整完整脚本的月份:
select target,
AorF,
Jan, Feb, Mar, Apr, May, Jun, Jul,
Aug, Sep, Oct, Nov, Dec
from
(
select a.target,
Left(a.monthname, 3) as [Month],
AorF,
value
from finalprojection a
left join finalactual b
on a.Target = b.Target
AND a.monthnum = b.MonthNum
cross apply
(
select 'A', b.Actual union all
select 'F', a.forecast
) c(AorF, value)
) d
pivot
(
max(value)
for month in (Jan, Feb, Mar, Apr, May, Jun, Jul,
Aug, Sep, Oct, Nov, Dec)
) piv
order by target;
见SQL Fiddle with Demo。这给出了最终结果:
| TARGET | AORF | JAN | FEB | MAR | APR | MAY | JUN | JUL | AUG | SEP | OCT | NOV | DEC |
|--------|------|---------------|----------------|----------------|---------------|--------------|---------------|----------------|--------------|------------|--------------|-------------|--------------|
| C:\ | A | (null) | 62927.87890625 | 64534.62109375 | 67215.296875 | 70991.046875 | 69857.109375 | 64440.69921875 | 64359.078125 | (null) | (null) | (null) | (null) |
| C:\ | F | 68260.1328125 | 65609.2890625 | 65850.2734375 | 66091.2578125 | 66332.25 | 66573.2265625 | 66814.21875 | 67055.203125 | 67296.1875 | 67537.171875 | 67778.15625 | 68019.140625 |
| E:\ | A | (null) | 382691.40625 | 400543.90625 | 418160.40625 | 435643.1875 | 451213.5 | 466608.1875 | 476218.1875 | (null) | (null) | (null) | (null) |
| E:\ | F | 560371.8125 | 385251 | 401171.09375 | 417091.1875 | 433011.3125 | 448937.3125 | 464851.40625 | 480771.40625 | 496691.5 | 512611.59375 | 528531.625 | 544451.8125 |
如果您需要根据开始月份对列进行不同的排序,那么您必须使用类似于以下的动态SQL:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@start int
set @start = 8
select @cols = STUFF((SELECT ',' + QUOTENAME(Left(monthname, 3))
from finalprojection
where MonthNum > (@start - 6)
and MonthNum <= (@start + 6)
group by monthNum,MonthName
order by MonthNum
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT target, AorF,' + @cols + '
from
(
select a.target,
Left(a.monthname, 3) as [Month],
AorF,
value
from finalprojection a
left join finalactual b
on a.Target = b.Target
AND a.monthnum = b.MonthNum
cross apply
(
select ''A'', b.Actual union all
select ''F'', a.forecast
) c (AorF, value)
) x
pivot
(
max(value)
for month in (' + @cols + ')
) p
order by target'
exec sp_executesql @query;
请参阅Demo
答案 1 :(得分:1)
根据运行的月份,我根本不明白列的含义是不同的。如果你能解释我可以帮助找到解决方案。这个查询看起来很冗长,但是一旦你将其分解,它实际上非常简单。这是使用所谓的交叉表。为了打破实际和预测,我分别做了它们,然后使用UNION将它们重新组合在一起。
with MyCte as
(
select a.target
, a.monthnum
, b.Actual
, a.forecast
, ROW_NUMBER() over(partition by a.target order by a.monthnum) as RowNum
from finalprojection a
left join finalactual b on a.Target = b.Target AND a.monthnum = b.MonthNum
)
select Target
, 'A' as [A/F]
, max(case when monthnum = 2 then Actual end) as Feb
, max(case when monthnum = 3 then Actual end) as Mar
, max(case when monthnum = 4 then Actual end) as Apr
, max(case when monthnum = 5 then Actual end) as May
, max(case when monthnum = 6 then Actual end) as Jun
, max(case when monthnum = 7 then Actual end) as Jul
, max(case when monthnum = 8 then Actual end) as Aug
, max(case when monthnum = 9 then Actual end) as Sep
, max(case when monthnum = 10 then Actual end) as Oct
, max(case when monthnum = 11 then Actual end) as Nov
, max(case when monthnum = 12 then Actual end) as Dec
, max(case when monthnum = 1 then Actual end) as Jan
from MyCte
group by Target
union all
select Target
, 'F' as [A/F]
, max(case when monthnum = 2 then Forecast end) as Feb
, max(case when monthnum = 3 then Forecast end) as Mar
, max(case when monthnum = 4 then Forecast end) as Apr
, max(case when monthnum = 5 then Forecast end) as May
, max(case when monthnum = 6 then Forecast end) as Jun
, max(case when monthnum = 7 then Forecast end) as Jul
, max(case when monthnum = 8 then Forecast end) as Aug
, max(case when monthnum = 9 then Forecast end) as Sep
, max(case when monthnum = 10 then Forecast end) as Oct
, max(case when monthnum = 11 then Forecast end) as Nov
, max(case when monthnum = 12 then Forecast end) as Dec
, max(case when monthnum = 1 then Forecast end) as Jan
from MyCte
group by Target
order by Target, [A/F]
答案 2 :(得分:1)
以下是基于您提供结果的查询的数据透视表。它分别进行实际和预测。要使列具有不同的顺序,您需要以不同的顺序选择它们。
SELECT Target, 'Actual' AS [A/F]
, [February], [March], [April], [May], [June], [July], [August]
, [September], [October], [November], [December], [January]
FROM (
SELECT [Target], [Month], [Actual] FROM (
select a.target, a.monthnum as 'Month Value', case when a.monthnum <= 12 then
a.monthnum else a.monthnum-12 end as 'Month Number', a.monthname as [Month],
b.Actual as 'Actual', a.forecast
from @finalprojection a left join @finalactual b on a.Target = b.Target AND a.monthnum = b.MonthNum
) AS YourTable
) AS SourceTable
PIVOT (
SUM([Actual]) FOR [Month] IN ([February], [March], [April], [May], [June], [July], [August]
, [September], [October], [November], [December], [January])
) AS PivotData
UNION ALL
SELECT Target, 'Forecast' AS [A/F]
, [February], [March], [April], [May], [June], [July], [August]
, [September], [October], [November], [December], [January]
FROM (
SELECT [Target], [Month], [forecast] FROM (
select a.target, a.monthnum as 'Month Value', case when a.monthnum <= 12 then
a.monthnum else a.monthnum-12 end as 'Month Number', a.monthname as [Month],
b.Actual as 'Actual', a.forecast
from @finalprojection a left join @finalactual b on a.Target = b.Target AND a.monthnum = b.MonthNum
) AS YourTable
) AS SourceTable
PIVOT (
SUM([forecast]) FOR [Month] IN ([February], [March], [April], [May], [June], [July], [August]
, [September], [October], [November], [December], [January])
) AS PivotData
当我使用您提供的数据运行时,我得到以下内容:
Target A/F February March April May June July August September October November December January
C:\ Actual 62927.87890625 64534.62109375 67215.296875 70991.046875 69857.109375 64440.69921875 64359.078125 NULL NULL NULL NULL NULL
E:\ Actual 382691.40625 400543.90625 418160.40625 435643.1875 451213.5 466608.1875 476218.1875 NULL NULL NULL NULL NULL
C:\ Forecast 65609.2890625 65850.2734375 66091.2578125 66332.25 66573.2265625 66814.21875 67055.203125 67296.1875 67537.171875 67778.15625 68019.140625 68260.1328125
E:\ Forecast 385251 401171.09375 417091.1875 433011.3125 448937.3125 464851.40625 480771.40625 496691.5 512611.59375 528531.625 544451.8125 560371.8125
请注意,数据透视表使用了所有数据的总和 - 如果您为每个目标设置了多个条目,那么可能会给您带来狡猾的结果。月。这是因为枢轴需要分组。这可能是您的月份顺序问题出现的地方,但我需要您更具体地确定。