我正在尝试查询某些交易数据,以便在每月末为每个报告建立CurrentProductionHours
值。
假设每个月每个报告都有一个交易,这非常简单......我可以使用下面代码中的某些内容按月对事务进行分区,然后选择{{1 }} = 1(实际上,每个月每个报告的最后一笔交易)。
TransactionByMonth
我遇到的问题是每个月份每个报告不一定会有交易...当这是个案时,我需要将最后一次已知的 SELECT
ReportId,
TransactionId,
CurrentProductionHours,
ROW_NUMBER() OVER (PARTITION BY [ReportId], [CalendarYear], [MonthOfYear]
ORDER BY TransactionTimestamp desc
) AS TransactionByMonth
FROM
tblSource
值继续到没有交易的月份,因为这表明没有变化。潜在地,这个值可能需要多次结转。
来源数据:
CurrentProductionHours
目标结果:
ReportId TransactionTimestamp CurrentProductionHours
1 2014-01-05 13:37:00 14.50
1 2014-01-20 09:15:00 15.00
1 2014-01-21 10:20:00 10.00
2 2014-01-22 09:43:00 22.00
1 2014-02-02 08:50:00 12.00
我还应该提一下,我有一个可用的日期表,如果需要可以参考。
** 更新05/03/2014 **
我现在有查询正在生成结果,如下面的例子所示,但我留下了数据孤岛(当月存在交易)和两者之间的差距...我的问题仍然类似,但在一些更通用的方法 - 如果您将以下数据集作为起点,填补数据岛之间间隙的最佳方法是什么?
ReportId Month Year ProductionHours
1 1 2014 10.00
2 1 2014 22.00
1 2 2014 12.00
2 2 2014 22.00
任何有关如何解决这个问题的建议都将不胜感激!
答案 0 :(得分:0)
试试这个:
;with a as
(
select dateadd(m, datediff(m, 0, min(TransactionTimestamp))+1,0) minTransactionTimestamp,
max(TransactionTimestamp) maxTransactionTimestamp from tblSource
), b as
(
select minTransactionTimestamp TT, maxTransactionTimestamp
from a
union all
select dateadd(m, 1, TT), maxTransactionTimestamp
from b
where tt < maxTransactionTimestamp
), c as
(
select distinct t.ReportId, b.TT from tblSource t
cross apply b
)
select c.ReportId,
month(dateadd(m, -1, c.TT)) Month,
year(dateadd(m, -1, c.TT)) Year,
x.CurrentProductionHours
from c
cross apply
(select top 1 CurrentProductionHours from tblSource
where TransactionTimestamp < c.TT
and ReportId = c.ReportId
order by TransactionTimestamp desc) x
答案 1 :(得分:0)
类似的方法,但使用笛卡尔来获得报告ID /月的所有组合。 在第一步。 第二步是向该笛卡尔添加源表中的最大时间戳,其中月份小于或等于当前行中的月份。 最后,它通过报告ID /时间戳将源表连接到临时表,以获取每个报告ID /月的最新源表行。
;
WITH allcombinations -- Cartesian (reportid X yearmonth)
AS ( SELECT reportid ,
yearmonth
FROM ( SELECT DISTINCT
reportid
FROM tblSource
) a
JOIN ( SELECT DISTINCT
DATEPART(yy, transactionTimestamp)
* 100 + DATEPART(MM,
transactionTimestamp) yearmonth
FROM tblSource
) b ON 1 = 1
),
maxdates --add correlated max timestamp where the month is less or equal to the month in current record
AS ( SELECT a.* ,
( SELECT MAX(transactionTimestamp)
FROM tblSource t
WHERE t.reportid = a.reportid
AND DATEPART(yy, t.transactionTimestamp)
* 100 + DATEPART(MM,
t.transactionTimestamp) <= a.yearmonth
) maxtstamp
FROM allcombinations a
)
-- join previous data to the source table by reportid and timestamp
SELECT distinct m.reportid ,
m.yearmonth ,
t.CurrentProductionHours
FROM maxdates m
JOIN tblSource t ON t.transactionTimestamp = m.maxtstamp and t.reportid=m.reportid
ORDER BY m.reportid ,
m.yearmonth