SQL从事务中生成定期快照表
我试图在事实之后从数据库的事务表中创建定期快照视图。交易表具有以下字段:SQL从事务中生成定期快照表
- ACCOUNT_ID(外键)
- EVENT_ID
- status_dt
- status_cd
每次帐户改变了应用程序的状态,新的行以新状态添加到交易表中。我想创建一个视图,显示每个日期的状态帐户数量;它应该具有以下字段:
- snapshot_dt
- status_cd
- count_of_accounts
这将让任何给定的一天计数,但不是所有的日子:
SELECT status_cd, COUNT(account_id) AS count_of_accounts
FROM transactions
JOIN (
SELECT account_id, MAX(event_id) AS event_id
FROM transactions
WHERE status_dt <= DATE '2014-12-05') latest
USING (account_id, event_id)
GROUP BY status_cd
谢谢!
好的,这将很难解释。
在每个日期对应每种状态,你应该算两个值:
- 谁与状态开始客户的数量。
- 以此状态离开的客户数量。
第一个值很简单。它只是按日期和状态汇总交易。
第二个值几乎一样容易。您将获得之前的状态码,并计算该状态码在该日期“离开”的次数。
然后,关键是第一个值的累加和减去第二个值的累加和。
我坦率地承认,下面的代码没有经过测试(如果你有一个SQL小提琴,我很乐意测试它)。但是,这是生成的查询是什么样子:
select status_dte, status_cd,
(sum(inc_cnt) over (partition by status_cd order by status_dt) -
sum(dec_cnt) over (partition by status_cd order by status_dt)
) as dateamount
from ((select t.status_dt, t.status_cd, count(*) as inc_cnt, 0 as dec_cnt
from transactions t
group by t.status_dt, t.status_cd
) union all
(select t.status_dt, prev_status_cd, 0, count(*)
from (select t.*
lag(t.status_cd) over (partition by t.account_id order by status_dt) as prev_status_cd
from transactions t
) t
where prev_status_cd is null
group by t.status_dt, prev_status_cd
)
) t;
如果您有日期,其中有一个或多个状态和要包括那些在输出没有变化,那么上面的查询需要使用cross join
首先在结果集中创建行。目前尚不清楚这是否是一项要求,所以我将这一并发症排除在外。
太棒了,非常感谢!在你的代码中有一个错字(应该是'prev_status_cd是**不是** null'),但除此之外它效果很好。 – Jared 2014-12-08 19:28:55
我想快照没有状态变化的日期。有没有比这更优雅的方式: 'SELECT DISTINCT status_dte, status_cd, (SUM(inc_cnt)OVER(PARTITION BY status_cd ORDER BY status_dte) - SUM(dec_cnt)OVER(PARTITION BY status_cd ORDER BY status_dte ))AS dateamount FROM(( SELECT status_dte,status_cd,0 AS inc_cnt,0 AS dec_cnt FROM( SELECT DISTINCT status_cd FROM交易) CROSS JOIN( SELECT DISTINCT status_dte FROM交易)) UNION ALL( ...' – Jared 2014-12-08 19:31:21
你使用了哪个数据库?我会猜测Oracle,但你应该明确问题上的标签。 – 2014-12-06 01:46:05
是的Oracle。谢谢你的提示!我主要发现将专有扩展从一个SQL转换为另一个并不困难,但不必非要。 – Jared 2014-12-07 17:22:07