我可以解释的问题是,我无法弄清楚如何将日期一个一个地输入另一个查询以在单个表中产生结果。我正在尝试将创建总计的查询视为我将日期输入的函数。一个日期,一个结果行,下一个日期,下一个结果行。我研究了循环,大多数人似乎都不喜欢它。我研究过以某种方式组合两个 CTE,一个构建我的日期表,另一个运行总计。对于还不熟悉 sql 的人来说,这现在超出了我的范围。
背景:
在我的系统中有一个“交易”表,每次更改某些组织参数(如其他表中的组织类型、组织子类型和组织状态)时都会添加一行。每个新行都记录了该组织当时所有变量的状态。这些行基于组织 ID 和更新 dttm 是唯一的。
组织编号 | 组织状况 | 组织类型 | 更新 DTTM | ... |
---|---|---|---|---|
55323 | 3 | 10 | 8/15/2002 上午 12:00:00 | ... |
14942 | 4 | 11 | 5/1/2008 上午 10:39:44 | ... |
14942 | 4 | 10 | 9/19/2008 上午 12:00:30 | ... |
19002 | 4 | 10 | 3/27/2023 上午 9:00:14 | ... |
在任何一天,都会更新几十个组织,从而产生几十个新行。有些组织每两周更新一次,表中有很多行。其他人不会经常更新,最新的一行可能是几个月或几年前写的,但是那一行将代表该组织的当前系统状态,因为此后没有记录任何更改。
我可以通过按 org_id 排序然后 update_dttm 降序排序,然后在应用 where 子句 update_dttm 后获取每个组织的第一行来有效地生成系统快照 < whatever snapshot date. Going further, I can also use a count or sum function to calculate the total number of orgs in each status state at on a given date. What I can't do is produce a query that would show me the totals for a series of dates in a single results table.
我已经很接近了:
DECLARE @Start date
DECLARE @End date
DECLARE @counter date
set @Start = '2020-01-01' --could be any start date from this century
set @End = getdate()
set @counter = @Start
while @counter <= @End
begin
with Moment as
(
select ORG_ID, ORG_NAME, ORG_NUM_NAME, ORG_TYPE, ORG_SUBTYPE, STATUS, UPDATE_DTTM,
ROW_NUMBER() OVER (
PARTITION BY ORG_ID
ORDER BY ORG_ID, UPDATE_DTTM desc
) AS [ROW NUMBER]
from TRANSACTIONS_TABLE
where UPDATE_DTTM < @counter
)
select count(case STATUS when '4' then 1 else null end) as Active,
count(case STATUS when '6' then 1 else null end) as Closed,
count(case STATUS when '5' then 1 else null end) as Dormant,
@counter as SystemDate
from Moment
where [ROW NUMBER] = 1
set @counter = (Select Dateadd(Month, 1, @counter)) --next result from next month
end
它给了我查询的每个系统日期的总计,但结果中的每一行都是它自己的表。
我正在寻找一张结果表。最终,我想将它带到 Power Query 并将其带入 Power BI,以制作一个简单的视觉效果来显示随时间的变化。如果我按原样使用该代码,Power Query 只会识别第一个结果。
提前致谢。
当您在
WHILE
循环中进行查询时,每次迭代都会得到一个结果。一个快速的解决方法是使用一个临时表并将结果插入到临时表中,然后在 while 循环的结尾,您可以从临时表中选择。
更好的解决方案是根本不使用无性能的 while 循环。在一个查询中完成。 (交叉应用中的内部查询基本上是您的原始查询,略有修改)
with
-- recrusive CTE to generate the list of dates
dates as
(
select [Date] = @Start
union all
select [Date] = dateadd(month, 1, [Date])
from dates
where [Date] < @End
)
-- and then use the dates to calcualte the Active,Closed,Dormant etc.
select t.Active, t.Closed, t.Dormant, d.Date as SystemDate
from dates d
cross apply
(
select count(case STATUS when '4' then 1 else null end) as Active,
count(case STATUS when '6' then 1 else null end) as Closed,
count(case STATUS when '5' then 1 else null end) as Dormant
from
(
select ORG_ID, STATUS,
ROW_NUMBER() OVER (PARTITION BY ORG_ID
ORDER BY ORG_ID, UPDATE_DTTM desc
) AS [RN]
from TRANSACTIONS_TABLE
where UPDATE_DTTM < d.Date
) t
where RN = 1
) t