Skip to content

从带符号视图路线进入。本任务维护同一张订单报表,交付三个连续版本:先同时修改订单和标签,再删最后一个最小金额,最后让一个分组消失。你要提交每批净变化和新快照,不只报最终总和。

1. 固定查询与旧快照 ​

Orders(customer,product,amount)含(a,p,10)两份、(a,p,30)一份、(b,q,5)一份。Tags(product,tag)含(p,hot)两份、(p,sale)一份、(q,sale)一份。所有列无NULL,金额为精确整数。按product等值内连接,投影到(customer,tag,amount),然后按(customer,tag)求COUNT、SUM、AVG、COUNT(DISTINCT amount)、MIN。

先逐种输出列旧连接重数:

元组 重数
(a,hot,10) 4
(a,hot,30) 2
(a,sale,10) 2
(a,sale,30) 1
(b,sale,5) 1

共10份,总金额155。三个旧摘要依次为a/hot:(6,100,50/3,2,10),a/sale:(3,50,50/3,2,10),b/sale:(1,5,5,1,5)。每个摘要元组只出现一次;其中的6或3不是摘要行重数。

2. 同时修改两侧,不能漏交叉项 ​

批1的Orders变化为(a,p,10)→−1、(a,p,20)→+1、(c,r,7)→+1。Tags变化为(p,hot)→−1、(p,sale)→+1、(r,sale)→+1。使用三项差分,交一张包含以下四列的表:J(ΔR,S)、J(R,ΔS)、J(ΔR,ΔS)、合计。前三项中的未加Δ的表都必须是版本0。

完整净变化为:

元组 净权
(a,hot,10) −3
(a,hot,20) +1
(a,hot,30) −1
(a,sale,20) +2
(a,sale,30) +1
(c,sale,7) +1

(a,sale,10)的三项为−1、+2、−1,净零,所以最终字典没有这一项。(a,hot,10)则为−2、−2、+1,合−3,旧4变新1;第三项不是凭空恢复一份已经删除的配对,而是纠正前两项对双删区域的重复扣除。新r键只有交叉项能产生结果。

新连接有11份、总金额192。请再按更新后的R'、S'从头连接,逐元组比对,而非只比总数与总和。两个汇总量相同不能保证具体结果相同。

本批三次直接扫描检查27个候选对,匹配13次;更新后的两表各有4个不同元组,全量重算检查16对。这里用增量方案是为了验证状态合同,不能把这个案例宣传成性能加速。若采用两项顺序式,第二项必须使用R',也可得到同一净变化。

3. 更新五列摘要,并把结果本身写成差分 ​

按频数状态与摘要撤回形成版本1:

分组 n sum avg distinct min
a/hot 3 60 20 3 10
a/sale 6 120 20 3 10
b/sale 1 5 5 1 5
c/sale 1 7 7 1 7

交付的摘要差分包含五个非零元组:a/hot旧行−1、新行+1;a/sale旧行−1、新行+1;c/sale新行+1。b/sale没有差分。a/hot的sum从100减到60,绝不是向“SUM=100”的旧摘要行施加−40份权重。

批2删除Orders最后一份(a,p,10)。上游应撤回a/hot金额10一份,a/sale金额10两份。两组的10频数都归零,新摘要为a/hot:(2,50,25,2,20),a/sale:(4,100,25,2,20)。交付两次旧行撤回和两次新行插入;MIN和distinct在两组都改变。

批3删除Tags最后一份(p,hot)。连接撤回(a,hot,20)、(a,hot,30)各一份,a/hot整组消失。摘要只撤回(a,hot,2,50,25,2,20),不补一行n=0。最终保留a/sale、b/sale、c/sale,份数合计6、金额合计112;这两个数等于剩余连接的COUNT/SUM之和。

4. 状态相同与输出相同要分开检查 ​

另起一份小任务:某组的金额为{1,2,5}。它的摘要是(3,8,8/3,3,1)。同批删除2、5,插入3、4,得到{1,3,4},五列摘要完全相同,所以摘要差分应为空。

尽管没有对外输出变化,内部频数必须更新。接着删除1,新MIN应为3;若上一批因“摘要没变”而跳过内部提交,便会错误得到2。这个迁移检查的是算子状态,而不是再换一组相似数字。

另一份组{−5,5}的sum为0,仍有n=2;它不能消失。空的普通分组不输出行,而全局聚合的数学辅助入口仍返回(0,0,未定义,0,未定义)。SQL空SUM/NULL合同不在本无NULL数学实例中。

5. 拒绝时不得交出半批结果 ​

版本3上请求删除不存在的(a,p,99),应报负重数错误,状态引用保持版本3。把期望版本写成2也应拒绝,即使变化为空。核验四类内容均未变:Orders、Tags、连接bag、全部组频数和摘要。

输入采用净变化,所以相同元组的+1和−1在同批相消,不能为了制造中间负值而先公开其中一半。最小双删例R=S=1给−1−1+1,合并后把旧输出1变成0;每项单独截负为零会留下错误结果。程序需用保留负值的字典加法。

最后将一个含2份同值元组的表与自身配对,再增加1份,结果从4变9。请给出2、2、1三个贡献;自连接也有两个逻辑输入槽,不能因只修改一张物理表而遗漏ΔR与自身的配对。

6. 可重跑交付 ​

下载标准库参考器,运行:

text
python foundation-view-delta-check.py
python -O foundation-view-delta-check.py

两次stdout应一致。公开事务入口为Maintainer及其apply(expected_epoch, orders_delta, tags_delta);内部signed_join、changed、prepare_groups使用已声明的正规化映射与合法旧状态前提。读者可以检查state,但不得修改其中字典。参考器是串行内存模型,没有实现SQL解析、持久恢复、外部消息去重或并发提交。

程序输出三批完整项、摘要、候选对账本和失败记录,并用逐出现全量连接/分组的另一条路径检查6000个有限批次。它提供的是实现与案例证据;每个成功版本为何正确,仍应由整数分配律、逐值频数不变量和唯一发布点解释。