先區分增量 重置與回捲
累計值日報不能看到負差就取絕對值。設備可能是人工歸零、重新啟動、固定modulus回捲、資料缺測或來源換機;每種情況的產量計算不同。本文用累計值980、995、5作虛構案例,先保存bootId、resetMarker、counterDefinition與讀值時間,再決定是否能算跨界增量。單次增量則直接代表該筆期間數量,不能與累計值混算。
| 情境 | 證據 | 995→5解讀 | 可計數 |
|---|---|---|---|
| 人工歸零 | resetMarker=R1 | 新週期起點 | 需另取5作歸零後數 |
| modulus=1000 | 規格明訂上限 | 回捲差=1000-995+5=10 | 可算10 |
| 重啟換機 | bootId改變 | 來源週期中斷 | 區間未知 |
| 無事件證據 | 只見負差 | 原因不明 | 保留Unknown |
若累計器定義是0到999且已知固定上限1000,並確認期間無重置且最多回捲一次時,995到5才可判為回捲,差值為5加上1000減995等於10。若是人工歸零,不能把10當成產量;5只是新週期讀值,重置前最後讀值995到實際重置之間增加多少仍未知,不能假定剛好多五件。
補送資料可能改變排序。先以sourceTimestamp和唯一樣本識別去重,再重算受影響區間;不要把同一讀值因receivedAt不同而加兩次。重算要增加calculationVersion,保存原先報表結果與修正理由。
跨班報表要在邊界建立明確規則:增量歸屬於結束時刻、開始時刻或以事件區間切分。若一個增量跨越19:00,不能默認整筆屬後班;設備能提供細粒度樣本時才可按時間分配,否則標註近似或未知。
每次重算應可重現輸入條件:查詢時間窗、時區、排序、去重鍵、reset判定規則與版本。只保存一個最後總數,下一次規則改變就無法解釋差異;保存逐筆增量和原因欄,才能檢查守恆。
日報審核者應能從總量反查每個加總項。若某段是人工歸零後的5,摘要需顯示它的週期和reset證據;若比較980到5且一次modulus回捲得到25,顯示公式與modulus;若某段Unknown,總量不能偷偷把它當零。
逐筆差分與跨班邊界
虛構日班在07:55讀980,08:05讀995,08:10讀5。若08:08有人工resetMarker,07:55到08:05增量為15,08:05前的累計屬上一週期;08:10的5屬新週期。若沒有marker,但另有證據排除重置且確認最多回捲一次,counterDefinition又明訂modulus1000,08:05到08:10可算10;若兩者都沒有,該段標Unknown,不用abs(5-995)=990。
| 時間 | 讀值 | 事件/boot | 判定增量 | 歸屬 |
|---|---|---|---|---|
| 07:55 | 980 | boot B1 | — | 前段 |
| 08:05 | 995 | B1 | 15 | 07:55–08:05 |
| 08:08 | — | reset R1 | — | 分界 |
| 08:10 | 5 | B1/R1後 | 5或未知 | 依證據 |
| 08:20 | 12 | B1/R1後 | 7 | 新週期 |
跨班日報要先定義邊界,例如07:00與19:00,再把每一筆增量放入區間。缺測從08:10到12:10時,即使12:10讀到40,也不能把40減5當成完整區間產量,除非能證明期間未重置、未換來源,並排除或確認回捲次數;中間沒有每筆取樣本身不妨礙以端點求區間總量,但無法知道區間內每分鐘分布。補送資料要按sourceTimestamp重排,但保留receivedAt,避免重複計數。
日報計算的第一步不是寫差分公式,而是確認計數器語意。要問它是每件增量、持續累計、班次重置或固定寬度暫存器;不同語意的負差處理完全不同。保存設備型號、計數寬度、上限、重置命令與保持條件,才能支持日後判讀。
多次回捲與未知區間
已知modulus可處理多次回捲,但必須知道每一段讀值間最多回捲幾次或有足夠事件。若讀值從980到5,一次回捲差值為25,公式是1000-980+5=25;若中間缺測很久,可能回捲兩次,差應是2×1000+5−980=1025,不能只算25。沒有回捲計數或上限證據時,保留區間未知。
| 前值 | 後值 | 已知條件 | 計算 | 結論 |
|---|---|---|---|---|
| 980 | 5 | 一次回捲上限、modulus1000 | 20+5=25 | 可支持25 |
| 995 | 5 | 一次回捲 | 5+5=10 | 可支持10 |
| 995 | 5 | 未知多次回捲 | 可能10、1010… | Unknown |
| 995 | 5 | 人工reset | 非回捲 | 5屬新週期 |
注意980到5的公式是1000-980+5=25;995到5才是1000-995+5=10。日報應列公式與證據,不只輸出結果。若資料源提供reset counter、bootId或事件,將它們和差分列關聯;若只提供一個累計值欄位,不能靠Postgres lag自行判定設備重置。
人工重置再加一組完整證據:08:08重置前已鎖存998,重置後確認為0,08:10讀5。則08:05的995到重置前增加3,重置後增加5,合計8;若拿不到998,只有重置後5可支持,前半段仍未知。這個8不能和modulus回捲的10互換,兩者依據不同。
日報驗收與資料限制
驗收至少做三組離線資料:人工歸零、已知一次modulus回捲、無證據負差。人工歸零報表要分前後週期;一次回捲計算符合公式;無證據案例顯示Unknown並列待補資料。再插入重複補送與跨班樣本,確認按唯一樣本ID去重,再核對sourceTimestamp排序與邊界歸屬。
報表欄位建議包含counterTag、sourceTimestamp、receivedAt、value、bootId、resetMarker、modulus、increment、quality、calculationVersion與reason。若人工補判,另記操作者、時間和依據,不能覆寫原始讀值。日平均或總量若含Unknown區間,摘要應顯示缺口與可支持範圍,而不是製造一個精確數字。
Postgres的lag等資料庫函數可以協助取得前一列,但它只處理資料列順序,不知道設備何時reset、是否回捲或中間漏測。需先定義事件與計數器規格,再使用平台函數實作;未指定設備與資料庫版本時不提供可直接執行SQL。
已知modulus1000的公式只適用每個取樣間最多一次回捲或有回捲次數證據。長時間沒資料時,995到5可能跨多圈;若沒有圈數,應標示下限或未知,不能把一次回捲結果當精確總量。
日報摘要若包含未知區間,應同時列已知產量、未知時間範圍、缺測筆數與待查證據。這比報出沒有依據的整數更能支援交班和後續設備調查。
報表遇到跨日重置時,先把reset事件放到時間線,再分配前後讀值。若 reset 的來源時間不明,只能標示邊界仍待確認;即使畫面看起來很接近午夜,也不能用收取時間代替發生時間。
多圈公式為增量=後值−前值+圈數×modulus,圈數來自可靠回捲計數或速率上限證據。若980到5跨三圈才是2025;若後值仍大於前值,也可能已多繞一圈,不能只在負差時檢查回捲。最大產出速率乘取樣間隔若已達一圈,就需要額外證據。
FAQ與來源
FAQ1:負差取絕對值可以快速修正嗎?不可以,會把人工歸零、回捲與缺測混成同一數字。
FAQ2:知道modulus1000就一定能算每段嗎?還要知道期間最多回捲次數與資料沒有重大缺口。
FAQ3:重啟後讀值變小是否就是歸零?不一定,需看bootId、reset事件與設備規格。
FAQ4:Postgres lag能判斷設備重置嗎?不能,它只能取得前一列,重置判定仍需設備證據。
參考:PostgreSQL 18窗口函數lag官方文件:依查詢順序取得前列值。
人工歸零事件應有操作者、時間、原因與前後值。若事件在07:00邊界附近,按sourceTimestamp歸屬並保留receivedAt;事件晚到不能把它任意移到收到的班次。若沒有reset marker,日報只報可支持區間與Unknown,不用補值遮掩缺口。
資料庫窗口函數只會按照ORDER BY取得前列。若排序欄位重複,結果順序可能不穩定;查詢要加來源序號或唯一鍵,並把設備證據放在資料模型中。
驗收表要列980到995的15、995到5的條件差異,以及980到5的25計算,避免把不同前值套用同一公式。對於無事件的負差,測試預期必須是Unknown而非一個看似合理的數字。
如果設備規格只說「計數器可重置」,卻未說明重置時保留值、上限或事件來源,日報設計應把這些列為待確認事項。工程師可以先產生未知區間報表,再等設備文件或實測資料補證,不把假設包裝成已驗證結果。