我有一个跟踪小部件位置的数据库(即跟踪单个项目而不是简单的 SKU 计数的库存系统)。
有两个相关的表:
InventoryUpdates (
UpdateId bigint PRIMARY KEY,
LocationId bigint,
Type tinyint, -- an enum column
DateTime datetimoffset
)
WidgetState {
SerialNumber varchar(20) PRIMARY KEY,
UpdateId bigint
}
解释:
库存更新可以是“完成”、“添加”或“减法”(这由Type
列确定)。当 Update 为Complete
时,它意味着相关的集合WidgetState
代表整个库存(即,如果列出了一个小部件,那么它就在那里;并且没有一个小部件是肯定的验证它当时不存在于库存中)。当 Update 为Additive
时,表示需要通过汇总Additive
自上次Complete
更新以来的所有后续更新来确定 Inventory(就像增量备份一样),最后Subtractive
更新意味着应将更新中包含的那些项目从清单中排除。当然,更新后可以出现多个Additive
和更新。Subtractive
Complete
所以我的问题是:
“给定最后一次Complete
更新和所有后续Additive
和Subtractive
更新的集合,获取一个位置的当前库存”
数据如下所示:
InventoryUpdates
----------------------------------------------
UpdateId LocationId Type DateTime
1 1 Complete 2014-01-01
2 1 Additive 2014-01-02
3 1 Subtractive 2014-01-03
4 1 Additive 2014-01-04
WidgetState
----------------------------------------------
SerialNumber UpdateId
0001 1
0004 1
008B 2
0001 3
0004 3
0004 4
在这个简单的示例中,我们看到唯一的小部件0004
在更新 1 的库存中是已知的,然后它在更新 3 中被删除,然后在更新 4 中重新添加。
假设我想找出当前库存,我的结果集应该是:
WidgetsInInventory
----------------------------------------------
SerialNumber
0004
008B
可能有一个非常简单的解决方案,我现在想不出。我想它可能看起来像这样:
SELECT
DISTINCT SerialNumber,
Type
FROM
WidgetState
INNER JOIN InventoryUpdates ON WidgetState.UpdateId = InventoryUpdates.UpdateId
WHERE
InventoryUpdates.Type = Complete OR
InventoryUpdates.Type = Additive
ORDER BY
InventoryUpdates.DateTime DESC
EXCEPT
SELECT
DISTINCT SerialNumber,
Type
FROM
WidgetState
INNER JOIN InventoryUpdates ON WidgetState.UpdateId = InventoryUpdates.UpdateId
WHERE
InventoryUpdates.Type = Subtractive
ORDER BY
InventoryUpdates.DateTime DESC
...但是当减法发生时,它就会分崩离析,而不管它可能发生在比后续加法更早的 DateTime 值的情况下。
更新
我只是在回家的路上想到这可能是一个可行的解决方案,我明天会测试它。
下面的代码使用DISTINCT
组合 withORDER BY
来获得each的最后一次出现WidgetState
,所以如果最后一次出现是 anAddition
那么它将取消任何 previous Subtraction
,反之亦然(好吧,如果最后一次出现是 aSubtraction
那么它可以很容易地被排除在外)来自带有WHERE Type <> Subtractive
谓词的未来超级查询)。03:00h 刚刚过去,我还没有机会尝试,但是这个理论听起来对吗?谢谢!
SELECT
WidgetState.SerialNumber,
InventoryUpdates.Type
FROM
WidgetState
INNER JOIN InventoryUpdates ON WidgetState.UpdateId = InventoryUpdates.UpdateId
WHERE
InventoryUpdates.DateTime >= @dateTimeOfLastCompleteUpdate
AND
InventoryUpdates.LocationId >= @locationId
GROUP BY
SerialNumber
ORDER BY
InventoryUpdates.DateTime DESC