系统涉及到保密,所以文中的东西统一用货物代替。
系统基本流程是设置一排排的货架,一个区域5个货架,一个货架上有3排(比喻,前面的信息是对保密系统的比喻),系统在对货架上的货物进行一次调整的时候都会保存一条调整记录。比如说:2022年12月01号xx点xx分xx秒调整《干脆面》(原货架01区1号货架2层)至(原货架01区2号货架2层),然后现在系统设计过程中发现一个疑点,客户通过监控发现了货架上的货物有问题,进行了截图。摆货架的人看不起截图上面的东西是什么,前几天还把货架中的东西清空去另一个区域了。现在就想根据时间,回溯到时间点上货架摆法的内容。
数据库运用的是postgresql,还有redis,后台用的springboot
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "jstzjl")
public class Jstzjl {
/**
* 作业编号
*/
@Id
@Column(name = "zybh")
private String zybh;
/**
* 商铺编号
*/
@Column(name = "jsbh")
private Integer jsbh;
/**
* 货物编号
*/
@Column(name = "rybh")
private String rybh;
/**
* 原货架号
*/
@Column(name = "yjsh")
private String yjsh;
/**
* 现货架号
*/
@Column(name = "xjsh")
private String xjsh;
/**
* 调整人
*/
@Column(name = "tjr")
private String tjr;
/**
* 调整人编号
*/
@Column(name = "tjrbh")
private String tjrbh;
/**
* 调整时间
*/
@Column(name = "tzsj")
private Date tzsj;
/**
* 调整原因
*/
@Column(name = "tzyy")
private String tzyy;
/**
* 调整原因代码(字典:调整原因)
*/
@Column(name = "tzyydm")
private String tzyydm;
/**
* 时间戳
*/
@Column(name = "sjc")
private Date sjc;
/**
* 更新时间
*/
@Column(name = "gxsj")
private Date gxsj;
/**
* 增删改类型:0增,1改,2.删
*/
@Column(name = "op")
private String op;
/**
* 数据回写第三方唯一标识
*/
@Column(name = "userid")
private String userid;
/**
* 调整审批作业编号
*/
@Column(name = "spzybh")
private String spzybh;
/**
* 原货架主管编号
*/
@Column(name = "yjsmjbh")
private String yjsmjbh;
/**
* 原货架主管姓名
*/
@Column(name = "yjsmjxm")
private String yjsmjxm;
/**
* 现货架主管姓名编号
*/
@Column(name = "xjsmjbh")
private String xjsmjbh;
/**
* 现货架主管姓名姓名
*/
@Column(name = "xjsmjxm")
private String xjsmjxm;
这是调整记录的表,基本上用的就是调整时间和原货架号和现货架号
原本我想的是根据时间一点点计算,比如说根据传入的时间,然后再去调整记录表依次查询调整时间在时间之后的数据展示。这样的操作过于挫,然后数据量一大的话,就会导致页面卡死。所以在这悬赏,希望各位可以提供一下好的思路。
暂时还没找到好用的解决办法。网上找到的基本上牛头不对马嘴。
可以定义一个查询该时间段内所有调整记录的方法,该方法以时间范围作为参数,返回调整记录列表。然后,循环该列表,对于每一个记录,按照记录中的原货架号和现货架号更新对应的货架上的货物内容。最后,返回该时间点的货架内容。
示例代码(假设使用JPA):
public List<Jstzjl> findByTzsjBetween(Date start, Date end) {
return jstzjlRepository.findByTzsjBetween(start, end);
}
public Map<String, List<String>> findGoodsAtPointInTime(Date date) {
Map<String, List<String>> shelfGoodsMap = new HashMap<>();
List<Jstzjl> jstzjlList = findByTzsjBetween(start, end);
for (Jstzjl jstzjl : jstzjlList) {
List<String> goods = shelfGoodsMap.getOrDefault(jstzjl.getYjsh(), new ArrayList<>());
goods.remove(jstzjl.getRybh());
List<String> newGoods = shelfGoodsMap.getOrDefault(jstzjl.getXjsh(), new ArrayList<>());
newGoods.add(jstzjl.getRybh());
}
return shelfGoodsMap;
}
update_time 调整时间,item_id物品id,to_box_id调整目标货架id
select max(update_time),item_id,to_box_id from update_record where update_time <= 20220104 group by item_id;
执行类似这样的sql,即可得到 时间点为20220104时的物品-货架的状态
看了好久才看明白,挺绕的。
设计表应该按照每次表变动的实体表进行快照保存,并且也要保存调整记录。 但进行快照保存数据量会特别大也有冗余数据。
设计调整记录表的初衷应该只是记录对表变动的人以及货物进行记录方便回溯变动的这个记录,而不是针对货物这个整体的变动检索的。
其他答主明显说错了,应该是查询时间节点之后的调整记录,而不是之前的调整记录。 并且是查询之后的所有记录,而非分页记录。
思路:
1、查询时间点及之后的时间点之间的调整数据,根据这部分数据计算出变动的数据,数据类的操作可以使用存储过程处理。
2、根据变动的数据与现有的仓库数据做回溯处理,可以使用视图处理。
3、查询当前回溯后的数据返回。
1,调整时间的时间戳作为一个唯一key作为一个字段,加索引
2,根据时间段获取数据时,根据分页数据返回(给出的时间段内数据可能比较多)
尽量一条sql获取结果,或者尽量缩小包含结果的颗粒度。