我认为这一定是一件相当普遍的事情,但我找不到一个例子。它涉及合并涉及日期/时间(或更一般地说是任何顺序值)的数据,而不包括冗余记录。冗余是指可以被其他记录暗示的记录。
例如,如果昨天的价格是 1 美元,今天的价格是 1 美元,并且昨天和今天之间没有其他价格变化,那么可以从昨天的价格推断出今天的价格,而不需要存储两天的价格。
这是我要解决的方案。我们有一个物品的历史价格表。新价格会定期导入表中。导入文件可以包含任何时间的日期,我们不知道它们总是在历史表中的数据“之后”。
为避免数据膨胀,我只想在记录提供新信息时插入记录。因此,如果可以从旧记录中推断出新记录,那么我不想插入新记录,如果可以从新记录中推断出旧记录,那么我想删除旧记录并插入新记录。
一些具体的例子可能会有所帮助,这里有两个问题场景:
传入记录可以从现有记录中推断出来,因此传入记录是冗余的。例如
旧记录:2013-04-23 1.00
新记录:2013-04-24 1.00 <--这是现有记录暗示的,不要插入
现有记录可以从新记录中推断出来,因此现有记录是多余的。例如
新纪录:2013-04-23 1.00
旧记录:2013-04-24 1.00 <--这是新记录暗示的,删除它
这只是显示一个值何时不是冗余的示例。例如
旧记录:2013-04-23 1.00
旧记录:2013-04-24 1.20
新记录:2013-04-25 1.00 <-- 不是多余的,价格自上次 1.00 起发生了变化
这里有一个更详细的例子http://sqlfiddle.com/#!3/2ef87/2
目前,我倾向于采用以下多步骤方法:
- 如果存在与较早日期具有相同价格的现有记录,则从收货中删除(上面的场景 1)。
- 从现有中删除具有相同价格且较早日期的传入记录(上面的场景 2)。
- 插入剩余的传入记录。
必须有更好的方法,也许使用 MERGE,但它正在努力解决如何做到这一点。
如何有效地“合并”现有记录和传入记录?谢谢
记录迟到的问题使重复删除更加复杂,但这并非不可能。使用视图(如您在其他问题中提出的那样)动态删除重复项是可行的,但针对该视图的查询可能会产生复杂和/或低效的查询计划。
另一种设计是将重复的记录保存在单独的表中,以防需要它们来正确处理未来的迟到记录。这确实给数据导入过程增加了一点复杂性,但每一步都不是太难,结果是一个干净整洁的无重复历史表:
表
初始数据
第一步是删除输入数据中的任何冗余,将删除的数据存储在新的保持表中:
分类输入行
下一步是确定输入表中的每一行是否是冗余的(相对于历史表)。以下查询
Action
适当地设置输入集数据的列:存储冗余行
现在我们将标识为冗余的行存储到保留表中:
新的历史记录行
非冗余行被添加到历史表中:
恢复冗余记录
添加新记录可能会导致需要恢复冗余行。以下查询识别合格的冗余行并将它们移动到历史表:
结果
历史表
历史重复表
处理新数据
前面的步骤很笼统。我们可以使用完全相同的代码处理一批新的行。下一个脚本加载包含两个样本行的输入表,其中一个是重复的,另一个是需要恢复先前冗余行的示例:
运行一般脚本的其余部分会产生这个最终状态:
历史:
历史副本:
(这更像是一个查询或“你确定你真的想这样做吗?”而不是一个答案,抱歉,评论太长了!)
如果较早的数据可以稍后进入,您真的要删除任何内容吗?可能会出现一个新数据点,这意味着您需要保留已删除的内容,例如:
然后
进来,你去重复
至
但是之后
到了,你想要
不是
但是您已经删除了 4th 的值。
由于过去的数据现在可以进来,当您只想考虑值变化而不是每次读数时,您可能需要保留所有内容并使用视图来筛选重复项。
如果我理解正确:
这可以通过使用像这样的 MERGE 子句来完成:
在这个小提琴中检查它,看看这是否是你想要的结果。